kards-env/kards_battle/game/game_state.py

360 lines
13 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.

"""
游戏状态管理
"""
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()
}
}