360 lines
13 KiB
Python
360 lines
13 KiB
Python
"""
|
||
游戏状态管理
|
||
"""
|
||
from typing import Optional, Dict, Any, List
|
||
from dataclasses import dataclass
|
||
from enum import Enum, auto
|
||
|
||
from ..core.enums import Nation, GamePhase
|
||
from ..core.battle_engine import BattleEngine
|
||
from ..cards.card_manager import CardManager
|
||
from ..cards.deck import Deck
|
||
from ..cards.card import BaseCard, CounterCard
|
||
|
||
|
||
class GameStatePhase(Enum):
|
||
"""游戏阶段枚举"""
|
||
INITIALIZATION = auto() # 初始化阶段
|
||
STRATEGIC_DEPLOYMENT = auto() # 战略调度阶段
|
||
GAME_ACTIVE = auto() # 游戏进行阶段
|
||
GAME_ENDED = auto() # 游戏结束阶段
|
||
|
||
|
||
@dataclass
|
||
class PlayerState:
|
||
"""玩家状态"""
|
||
name: str
|
||
player_id: int # 0 或 1
|
||
major_nation: Nation
|
||
minor_nation: Nation
|
||
card_manager: CardManager
|
||
kredits: int = 0 # 当前可用kredits
|
||
kredits_slot: int = 0 # kredits槽数
|
||
set_counters: List[CounterCard] = None # 已设置的反制卡
|
||
|
||
def __post_init__(self):
|
||
if self.set_counters is None:
|
||
self.set_counters = []
|
||
|
||
|
||
class GameState:
|
||
"""游戏状态管理器"""
|
||
|
||
def __init__(
|
||
self,
|
||
player1_name: str,
|
||
player1_deck: Deck,
|
||
player2_name: str,
|
||
player2_deck: Deck,
|
||
debug_mode: bool = False
|
||
):
|
||
# 基础游戏信息
|
||
self.debug_mode = debug_mode
|
||
self.phase = GameStatePhase.INITIALIZATION
|
||
|
||
# 创建战斗引擎
|
||
self.battle_engine = BattleEngine(player1_name, player2_name, debug_mode)
|
||
|
||
# 创建玩家状态
|
||
self.player1 = PlayerState(
|
||
name=player1_name,
|
||
player_id=0,
|
||
major_nation=player1_deck.major_nation,
|
||
minor_nation=player1_deck.minor_nation,
|
||
card_manager=CardManager(player1_deck)
|
||
)
|
||
|
||
self.player2 = PlayerState(
|
||
name=player2_name,
|
||
player_id=1,
|
||
major_nation=player2_deck.major_nation,
|
||
minor_nation=player2_deck.minor_nation,
|
||
card_manager=CardManager(player2_deck)
|
||
)
|
||
|
||
# 游戏流程状态
|
||
self.current_turn = 1
|
||
self.active_player_id = 0 # 当前行动玩家 (0 或 1)
|
||
|
||
# 先后手确定
|
||
self.first_player_id = 0 # 先手玩家
|
||
self.second_player_id = 1 # 后手玩家
|
||
|
||
# 游戏结束状态
|
||
self.game_ended = False
|
||
self.winner_id: Optional[int] = None
|
||
self.end_reason = ""
|
||
|
||
# 事件历史
|
||
self.event_history = []
|
||
|
||
# 初始化游戏
|
||
self._initialize_game()
|
||
|
||
def _initialize_game(self):
|
||
"""初始化游戏状态"""
|
||
# 部署HQ到战场
|
||
self._deploy_hqs()
|
||
|
||
# 初始抽牌
|
||
self._initial_card_draw()
|
||
|
||
# 进入战略调度阶段
|
||
self.phase = GameStatePhase.STRATEGIC_DEPLOYMENT
|
||
|
||
if self.debug_mode:
|
||
print(f"游戏初始化完成")
|
||
print(f"先手玩家: {self.get_player(self.first_player_id).name}")
|
||
print(f"后手玩家: {self.get_player(self.second_player_id).name}")
|
||
|
||
def _deploy_hqs(self):
|
||
"""部署双方的HQ到战场"""
|
||
# 创建HQ并部署到支援线
|
||
from ..battlefield.battlefield import HQ
|
||
|
||
# 玩家1的HQ
|
||
hq1 = HQ(player_id=self.player1.name)
|
||
self.battle_engine.battlefield.player1_support.objectives.append(hq1)
|
||
|
||
# 玩家2的HQ
|
||
hq2 = HQ(player_id=self.player2.name)
|
||
self.battle_engine.battlefield.player2_support.objectives.append(hq2)
|
||
|
||
if self.debug_mode:
|
||
print(f"HQ部署完成: {self.player1.name} vs {self.player2.name}")
|
||
|
||
def _initial_card_draw(self):
|
||
"""初始抽牌"""
|
||
# 先手玩家摸4张牌
|
||
first_player = self.get_player(self.first_player_id)
|
||
first_cards = first_player.card_manager.initial_draw(4)
|
||
|
||
# 后手玩家摸5张牌
|
||
second_player = self.get_player(self.second_player_id)
|
||
second_cards = second_player.card_manager.initial_draw(5)
|
||
|
||
if self.debug_mode:
|
||
print(f"{first_player.name} 初始摸牌: {len(first_cards)}张")
|
||
print(f"{second_player.name} 初始摸牌: {len(second_cards)}张")
|
||
|
||
def get_player(self, player_id: int) -> PlayerState:
|
||
"""获取玩家状态"""
|
||
if player_id == 0:
|
||
return self.player1
|
||
elif player_id == 1:
|
||
return self.player2
|
||
else:
|
||
raise ValueError(f"无效的玩家ID: {player_id}")
|
||
|
||
def get_current_player(self) -> PlayerState:
|
||
"""获取当前行动玩家"""
|
||
return self.get_player(self.active_player_id)
|
||
|
||
def get_opponent(self, player_id: int) -> PlayerState:
|
||
"""获取对手玩家"""
|
||
return self.get_player(1 - player_id)
|
||
|
||
def get_current_player_id(self) -> int:
|
||
"""获取当前行动玩家ID"""
|
||
return self.active_player_id
|
||
|
||
def get_battlefield(self):
|
||
"""获取战场"""
|
||
return self.battle_engine.battlefield
|
||
|
||
def get_battle_engine(self) -> BattleEngine:
|
||
"""获取战斗引擎"""
|
||
return self.battle_engine
|
||
|
||
def can_perform_strategic_deployment(self, player_id: int) -> bool:
|
||
"""检查玩家是否可以进行战略调度"""
|
||
if self.phase != GameStatePhase.STRATEGIC_DEPLOYMENT:
|
||
return False
|
||
|
||
player = self.get_player(player_id)
|
||
return not player.card_manager.strategic_deployment_completed
|
||
|
||
def perform_strategic_deployment(self, player_id: int, cards_to_mulligan: List[BaseCard]) -> List[BaseCard]:
|
||
"""
|
||
执行战略调度
|
||
|
||
Args:
|
||
player_id: 玩家ID
|
||
cards_to_mulligan: 要重抽的卡牌
|
||
|
||
Returns:
|
||
新抽到的卡牌列表
|
||
"""
|
||
if not self.can_perform_strategic_deployment(player_id):
|
||
raise ValueError("当前不能进行战略调度")
|
||
|
||
player = self.get_player(player_id)
|
||
new_cards = player.card_manager.strategic_deployment(cards_to_mulligan)
|
||
|
||
if self.debug_mode:
|
||
print(f"{player.name} 完成战略调度,重抽了 {len(cards_to_mulligan)} 张牌")
|
||
|
||
return new_cards
|
||
|
||
def is_strategic_deployment_complete(self) -> bool:
|
||
"""检查是否所有玩家都完成了战略调度"""
|
||
return (self.player1.card_manager.strategic_deployment_completed and
|
||
self.player2.card_manager.strategic_deployment_completed)
|
||
|
||
def start_main_game(self):
|
||
"""开始正式游戏"""
|
||
if self.phase != GameStatePhase.STRATEGIC_DEPLOYMENT:
|
||
raise ValueError("必须在战略调度阶段后才能开始正式游戏")
|
||
|
||
if not self.is_strategic_deployment_complete():
|
||
# 自动完成未完成的战略调度(不重抽任何卡)
|
||
if not self.player1.card_manager.strategic_deployment_completed:
|
||
self.perform_strategic_deployment(0, [])
|
||
if not self.player2.card_manager.strategic_deployment_completed:
|
||
self.perform_strategic_deployment(1, [])
|
||
|
||
# 进入游戏进行阶段
|
||
self.phase = GameStatePhase.GAME_ACTIVE
|
||
|
||
# 设置当前玩家为先手
|
||
self.active_player_id = self.first_player_id
|
||
|
||
# 开始先手玩家的第一回合(不摸牌)
|
||
self._start_player_turn(draw_card=False)
|
||
|
||
if self.debug_mode:
|
||
print(f"正式游戏开始,先手玩家: {self.get_current_player().name}")
|
||
|
||
def _start_player_turn(self, draw_card: bool = True):
|
||
"""
|
||
开始玩家回合
|
||
|
||
Args:
|
||
draw_card: 是否摸牌(先手第一回合不摸牌)
|
||
"""
|
||
current_player = self.get_current_player()
|
||
|
||
# 更新kredits系统
|
||
self._update_kredits_system()
|
||
|
||
# 摸牌(除了先手第一回合)
|
||
if draw_card:
|
||
def hq_damage_callback(damage: int):
|
||
"""HQ疲劳伤害回调"""
|
||
battlefield = self.get_battlefield()
|
||
if current_player.player_id == 0:
|
||
hq = battlefield.player1_support.get_hq()
|
||
else:
|
||
hq = battlefield.player2_support.get_hq()
|
||
|
||
if hq:
|
||
actual_damage = hq.take_damage(damage)
|
||
if self.debug_mode:
|
||
print(f"{current_player.name} 的HQ受到疲劳伤害: {actual_damage}")
|
||
|
||
# 检查游戏是否结束
|
||
if hq.is_destroyed():
|
||
self._end_game(1 - current_player.player_id, "HQ被摧毁(疲劳)")
|
||
|
||
drawn_card = current_player.card_manager.draw_card(hq_damage_callback)
|
||
if self.debug_mode and drawn_card:
|
||
print(f"{current_player.name} 摸牌: {drawn_card.name}")
|
||
|
||
if self.debug_mode:
|
||
print(f"回合 {self.current_turn}: {current_player.name} 的回合开始")
|
||
print(f"Kredits: {current_player.kredits}/{current_player.kredits_slot}")
|
||
|
||
def _update_kredits_system(self):
|
||
"""更新kredits系统"""
|
||
current_player = self.get_current_player()
|
||
|
||
# 增长kredits槽(最大12)
|
||
if current_player.kredits_slot < 12:
|
||
current_player.kredits_slot += 1
|
||
|
||
# 重置当前kredits为槽数
|
||
current_player.kredits = current_player.kredits_slot
|
||
|
||
# 同步战斗引擎的kredits
|
||
if current_player.player_id == 0:
|
||
self.battle_engine.player1_kredits_slot = current_player.kredits_slot
|
||
self.battle_engine.player1_kredits = current_player.kredits
|
||
else:
|
||
self.battle_engine.player2_kredits_slot = current_player.kredits_slot
|
||
self.battle_engine.player2_kredits = current_player.kredits
|
||
|
||
def end_turn(self):
|
||
"""结束当前玩家回合"""
|
||
if self.phase != GameStatePhase.GAME_ACTIVE:
|
||
raise ValueError("只能在游戏进行阶段结束回合")
|
||
|
||
current_player = self.get_current_player()
|
||
|
||
if self.debug_mode:
|
||
print(f"{current_player.name} 结束回合")
|
||
|
||
# 切换到对手
|
||
self.active_player_id = 1 - self.active_player_id
|
||
|
||
# 如果切换到先手玩家,增加回合数
|
||
if self.active_player_id == self.first_player_id:
|
||
self.current_turn += 1
|
||
|
||
# 开始对手回合
|
||
self._start_player_turn(draw_card=True)
|
||
|
||
# 同步战斗引擎的状态
|
||
self.battle_engine.active_player = self.active_player_id
|
||
self.battle_engine.current_turn = self.current_turn
|
||
|
||
def _end_game(self, winner_id: int, reason: str):
|
||
"""结束游戏"""
|
||
self.game_ended = True
|
||
self.winner_id = winner_id
|
||
self.end_reason = reason
|
||
self.phase = GameStatePhase.GAME_ENDED
|
||
|
||
winner = self.get_player(winner_id)
|
||
if self.debug_mode:
|
||
print(f"游戏结束!获胜者: {winner.name} ({reason})")
|
||
|
||
def check_win_condition(self):
|
||
"""检查胜利条件"""
|
||
if self.game_ended:
|
||
return
|
||
|
||
# 检查HQ是否被摧毁
|
||
battlefield = self.get_battlefield()
|
||
|
||
hq1 = battlefield.player1_support.get_hq()
|
||
if hq1 and hq1.is_destroyed():
|
||
self._end_game(1, "摧毁敌方HQ")
|
||
return
|
||
|
||
hq2 = battlefield.player2_support.get_hq()
|
||
if hq2 and hq2.is_destroyed():
|
||
self._end_game(0, "摧毁敌方HQ")
|
||
return
|
||
|
||
def get_game_statistics(self) -> Dict[str, Any]:
|
||
"""获取游戏统计信息"""
|
||
return {
|
||
'current_turn': self.current_turn,
|
||
'phase': self.phase.name,
|
||
'active_player': self.get_current_player().name,
|
||
'game_ended': self.game_ended,
|
||
'winner': self.get_player(self.winner_id).name if self.winner_id is not None else None,
|
||
'end_reason': self.end_reason,
|
||
'player1_stats': {
|
||
'name': self.player1.name,
|
||
'nations': f"{self.player1.major_nation}/{self.player1.minor_nation}",
|
||
'kredits': f"{self.player1.kredits}/{self.player1.kredits_slot}",
|
||
'card_stats': self.player1.card_manager.get_statistics()
|
||
},
|
||
'player2_stats': {
|
||
'name': self.player2.name,
|
||
'nations': f"{self.player2.major_nation}/{self.player2.minor_nation}",
|
||
'kredits': f"{self.player2.kredits}/{self.player2.kredits_slot}",
|
||
'card_stats': self.player2.card_manager.get_statistics()
|
||
}
|
||
} |