kards-env/kards_battle/game/game_state.py

360 lines
13 KiB
Python
Raw Permalink Normal View History

2025-09-05 17:05:43 +08:00
"""
游戏状态管理
"""
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()
}
}