Files
shortdeck/shortdeck_server/arena_adapter.py
2025-10-09 15:28:34 +08:00

166 lines
5.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import uuid
from typing import List, Optional, Dict
from shortdeck_arena.simulation import Simulation
from shortdeck_arena.agent import Agent, HumanAgent
from shortdeck_arena.game_stage import BlindConfig
class ArenaGame:
def __init__(self, starting_stack: int = 1000, max_players: int = 6,
small_blind: int = 1, big_blind: int = 2):
self.agents = []
self.player_names: List[str] = []
self.starting_stack = starting_stack
self.max_players = max_players
self.sim: Optional[Simulation] = None
self.blind_config = BlindConfig(small_blind, big_blind, ante=0)
self.game_id = str(uuid.uuid4())
def join_game(self, name) -> int:
if len(self.agents) >= self.max_players:
raise ValueError("Game is full")
player_id = len(self.agents)
agent = HumanAgent(player_id)
self.agents.append(agent)
self.player_names.append(name)
if len(self.agents) == 1:
self.sim = Simulation(self.agents, blind_config=self.blind_config)
# 筹码默认1000
self.sim.stacks = [self.starting_stack] * len(self.agents)
elif self.sim:
self.sim.agents = self.agents
self.sim.player_states.append(self.sim.player_states[0].__class__.ACTIVE)
self.sim.pot.append(0)
self.sim.stacks.append(self.starting_stack)
# 当有至少2个玩家时触发新一轮
if len(self.agents) >= 2 and self.sim:
self.sim.stacks = [self.starting_stack] * len(self.agents)
self.sim.new_round()
return player_id
def apply_action(self, player_id, action, amount: Optional[int] = None) -> dict:
if not self.sim:
return {"success": False, "message": "游戏未开始"}
try:
self.sim.apply_action(player_id, action, amount)
self.sim.dump_data()
return {"success": True, "message": f"Applied {action}"}
except Exception as e:
return {"success": False, "message": str(e)}
def info(self, player_id: Optional[int] = None) -> Dict:
if not self.sim:
return {"error": "游戏未初始化"}
info_data = {
"game_id": self.game_id,
"players": self.player_names,
"dealer_index": self.sim.dealer_position,
"current_turn": self.sim.current_turn,
"stage": self.sim.current_stage.value,
"total_pot": self.sim.total_pot,
"side_pots": [{"amount": pot.amount, "eligible_players": list(pot.eligible_players)}
for pot in self.sim.get_side_pots()],
}
if player_id is not None and 0 <= player_id < len(self.sim.stacks):
try:
player_cards = self.sim.player_cards(player_id)
info_data["player_cards"] = [str(card) for card in player_cards]
except Exception:
info_data["player_cards"] = []
info_data["actions"] = self.sim.get_available_actions(player_id)
else:
info_data["player_cards"] = []
info_data["actions"] = {"can_act": False, "reason": "Invalid player"}
try:
board_cards = self.sim.board_cards(self.sim.current_stage.value)
info_data["board_cards"] = [str(card) for card in board_cards]
except Exception:
info_data["board_cards"] = []
info_data["stacks"] = self.sim.stacks.copy()
info_data["player_states"] = [state.value for state in self.sim.player_states]
info_data["current_pot"] = self.sim.pot.copy()
return info_data
def get_hand_strength(self, player_id: int) -> Dict:
ranking = self.sim.evaluate_player_hand(player_id)
if ranking is None:
return {"error": "无法评估手牌"}
return {
"hand_type": ranking.hand_type.type_name,
"description": str(ranking),
"strength": ranking.get_strength(),
"cards": [str(card) for card in ranking.cards]
}
def check_hand_complete(self) -> bool:
return self.sim.is_hand_complete() if self.sim else False
def get_winners(self) -> Dict:
if not self.sim:
return {"error": "游戏未初始化"}
if not self.sim.is_hand_complete():
return {"error": "手牌未完成"}
return self.sim.complete_hand()
def showdown(self) -> Dict:
if not self.sim:
return {"error": "游戏未初始化"}
winners = self.sim.determine_winners()
showdown_info = {}
for pid, ranking in winners.items():
if ranking is not None:
showdown_info[pid] = {
"cards": [str(card) for card in self.sim.player_cards(pid)],
"hand_type": ranking.hand_type.type_name,
"description": str(ranking),
"strength": ranking.get_strength()
}
else:
showdown_info[pid] = {
"cards": [str(card) for card in self.sim.player_cards(pid)],
"hand_type": "Winner by default",
"description": "Other players folded",
"strength": float('inf')
}
return {
"showdown": showdown_info,
"pot_distribution": self.sim.distribute_pot()
}
@property
def pot(self) -> int:
return self.sim.total_pot if self.sim else 0
@property
def stacks(self) -> List[int]:
return self.sim.stacks if self.sim else []
@property
def current_turn(self) -> int:
return self.sim.current_turn if self.sim else -1
@property
def history(self) -> List[Dict]:
return self.sim.history if self.sim else []