""" Player 玩家抽象基类 支持人类玩家和 AI 玩家 """ from abc import ABC, abstractmethod from typing import Optional, Dict, Any from enum import Enum import uuid import time class PlayerType(Enum): HUMAN = "human" AI = "ai" class Player(ABC): """ 玩家抽象基类 封装玩家的通用属性和行为 """ def __init__(self, name: str, player_id: Optional[str] = None): self.id = player_id or f"player_{uuid.uuid4().hex[:8]}" self.name = name self.type: PlayerType = PlayerType.HUMAN # 连接状态 self.is_connected = False self.socket_id: Optional[str] = None self.connected_at: Optional[float] = None # 房间状态 self.room_id: Optional[str] = None self.seat_number: Optional[int] = None # 游戏状态 self.is_ready = False self.role: Optional[str] = None # landlord/farmer/red/black # 断线托管 self.is_ai_controlled = False # 是否处于AI托管模式 self.offline_since: Optional[float] = None # 离线时间戳 self.original_ai_control = False # 记录原始状态,用于恢复 # 统计数据 self.total_games = 0 self.win_count = 0 self.score = 0 @property @abstractmethod def is_ai(self) -> bool: """是否为 AI 玩家""" pass def connect(self, socket_id: str): """玩家连接""" self.socket_id = socket_id self.is_connected = True self.connected_at = time.time() def disconnect(self): """玩家断开连接""" self.socket_id = None self.is_connected = False self.offline_since = time.time() def enable_ai_control(self): """启用AI托管""" self.is_ai_controlled = True def disable_ai_control(self): """取消AI托管,恢复人工控制""" self.is_ai_controlled = False self.offline_since = None def join_room(self, room_id: str, seat: int): """加入房间""" self.room_id = room_id self.seat_number = seat def leave_room(self): """离开房间""" self.room_id = None self.seat_number = None self.is_ready = False self.role = None def set_ready(self, ready: bool = True): """设置准备状态""" self.is_ready = ready def to_dict(self, include_private: bool = False) -> Dict[str, Any]: """序列化为字典""" data = { 'id': self.id, 'name': self.name, 'type': self.type.value, 'is_ai': self.is_ai, 'is_connected': self.is_connected, 'is_ai_controlled': self.is_ai_controlled, 'seat_number': self.seat_number, 'is_ready': self.is_ready, 'role': self.role, } if include_private: data.update({ 'room_id': self.room_id, 'socket_id': self.socket_id, 'offline_since': self.offline_since, 'total_games': self.total_games, 'win_count': self.win_count, 'score': self.score, }) return data def __repr__(self): return f"<{self.__class__.__name__}(id={self.id[:8]}, name={self.name}, seat={self.seat_number})>" class HumanPlayer(Player): """人类玩家""" def __init__(self, name: str, player_id: Optional[str] = None): super().__init__(name, player_id) self.type = PlayerType.HUMAN @property def is_ai(self) -> bool: return False class AIPlayer(Player): """AI 玩家""" def __init__(self, name: str, ai_type: str, ai_config: Optional[Dict] = None): super().__init__(name) self.type = PlayerType.AI self.ai_type = ai_type # "rule", "minimax", "deepseek" self.ai_config = ai_config or {} self.is_connected = True # AI 始终在线 self.is_ready = True # AI 自动准备 @property def is_ai(self) -> bool: return True def to_dict(self, include_private: bool = False) -> Dict[str, Any]: data = super().to_dict(include_private) data['ai_type'] = self.ai_type return data