360 lines
11 KiB
Python
360 lines
11 KiB
Python
|
|
"""
|
|||
|
|
游戏主引擎 - 协调卡牌系统和战斗系统
|
|||
|
|
"""
|
|||
|
|
from typing import List, Optional, Tuple, Dict, Any
|
|||
|
|
|
|||
|
|
from ..core.enums import Nation, LineType
|
|||
|
|
from ..cards.deck import Deck, DeckBuilder
|
|||
|
|
from ..cards.card import BaseCard, UnitCard
|
|||
|
|
from ..cards.placeholder_cards import create_test_deck_cards
|
|||
|
|
from .game_state import GameState, GameStatePhase
|
|||
|
|
from .nation_config import NationConfig
|
|||
|
|
|
|||
|
|
|
|||
|
|
class GameEngineError(Exception):
|
|||
|
|
"""游戏引擎错误"""
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
|
|||
|
|
class GameEngine:
|
|||
|
|
"""
|
|||
|
|
游戏主引擎
|
|||
|
|
协调卡牌系统和战斗系统,管理完整的游戏流程
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
def __init__(self, debug_mode: bool = False):
|
|||
|
|
self.debug_mode = debug_mode
|
|||
|
|
self.game_state: Optional[GameState] = None
|
|||
|
|
|
|||
|
|
def create_test_game(
|
|||
|
|
self,
|
|||
|
|
player1_name: str = "Player1",
|
|||
|
|
player1_major: Nation = Nation.GERMANY,
|
|||
|
|
player1_minor: Nation = Nation.ITALY,
|
|||
|
|
player2_name: str = "Player2",
|
|||
|
|
player2_major: Nation = Nation.USA,
|
|||
|
|
player2_minor: Nation = Nation.UK
|
|||
|
|
) -> GameState:
|
|||
|
|
"""
|
|||
|
|
创建测试游戏
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
player1_name: 玩家1名称
|
|||
|
|
player1_major: 玩家1主国
|
|||
|
|
player1_minor: 玩家1盟国
|
|||
|
|
player2_name: 玩家2名称
|
|||
|
|
player2_major: 玩家2主国
|
|||
|
|
player2_minor: 玩家2盟国
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
游戏状态对象
|
|||
|
|
"""
|
|||
|
|
# 验证国家配置
|
|||
|
|
if not NationConfig.is_valid_major_minor_combo(player1_major, player1_minor):
|
|||
|
|
raise GameEngineError(f"玩家1的国家组合无效: {player1_major}/{player1_minor}")
|
|||
|
|
|
|||
|
|
if not NationConfig.is_valid_major_minor_combo(player2_major, player2_minor):
|
|||
|
|
raise GameEngineError(f"玩家2的国家组合无效: {player2_major}/{player2_minor}")
|
|||
|
|
|
|||
|
|
# 创建测试卡组
|
|||
|
|
player1_cards = create_test_deck_cards(player1_major, player1_minor)
|
|||
|
|
player2_cards = create_test_deck_cards(player2_major, player2_minor)
|
|||
|
|
|
|||
|
|
# 构建卡组
|
|||
|
|
player1_deck = DeckBuilder.build_deck(player1_major, player1_minor, player1_cards)
|
|||
|
|
player2_deck = DeckBuilder.build_deck(player2_major, player2_minor, player2_cards)
|
|||
|
|
|
|||
|
|
# 创建游戏状态
|
|||
|
|
self.game_state = GameState(
|
|||
|
|
player1_name, player1_deck,
|
|||
|
|
player2_name, player2_deck,
|
|||
|
|
debug_mode=self.debug_mode
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
if self.debug_mode:
|
|||
|
|
print(f"测试游戏创建成功:")
|
|||
|
|
print(f" {player1_name}: {player1_major}/{player1_minor}")
|
|||
|
|
print(f" {player2_name}: {player2_major}/{player2_minor}")
|
|||
|
|
|
|||
|
|
return self.game_state
|
|||
|
|
|
|||
|
|
def create_game_from_decks(
|
|||
|
|
self,
|
|||
|
|
player1_name: str,
|
|||
|
|
player1_deck: Deck,
|
|||
|
|
player2_name: str,
|
|||
|
|
player2_deck: Deck
|
|||
|
|
) -> GameState:
|
|||
|
|
"""
|
|||
|
|
从预构建的卡组创建游戏
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
player1_name: 玩家1名称
|
|||
|
|
player1_deck: 玩家1卡组
|
|||
|
|
player2_name: 玩家2名称
|
|||
|
|
player2_deck: 玩家2卡组
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
游戏状态对象
|
|||
|
|
"""
|
|||
|
|
self.game_state = GameState(
|
|||
|
|
player1_name, player1_deck,
|
|||
|
|
player2_name, player2_deck,
|
|||
|
|
debug_mode=self.debug_mode
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
return self.game_state
|
|||
|
|
|
|||
|
|
def get_current_game(self) -> Optional[GameState]:
|
|||
|
|
"""获取当前游戏状态"""
|
|||
|
|
return self.game_state
|
|||
|
|
|
|||
|
|
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.game_state:
|
|||
|
|
raise GameEngineError("游戏尚未创建")
|
|||
|
|
|
|||
|
|
return self.game_state.perform_strategic_deployment(player_id, cards_to_mulligan)
|
|||
|
|
|
|||
|
|
def start_main_game(self):
|
|||
|
|
"""开始正式游戏(完成战略调度阶段后)"""
|
|||
|
|
if not self.game_state:
|
|||
|
|
raise GameEngineError("游戏尚未创建")
|
|||
|
|
|
|||
|
|
self.game_state.start_main_game()
|
|||
|
|
|
|||
|
|
if self.debug_mode:
|
|||
|
|
print("正式游戏开始!")
|
|||
|
|
|
|||
|
|
def play_unit_card(
|
|||
|
|
self,
|
|||
|
|
player_id: int,
|
|||
|
|
card: UnitCard,
|
|||
|
|
target_position: Optional[Tuple[LineType, int]] = None
|
|||
|
|
) -> bool:
|
|||
|
|
"""
|
|||
|
|
打出单位卡牌
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
player_id: 玩家ID
|
|||
|
|
card: 要打出的单位卡
|
|||
|
|
target_position: 目标位置 (line_type, position)
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
是否成功打出
|
|||
|
|
"""
|
|||
|
|
if not self.game_state:
|
|||
|
|
raise GameEngineError("游戏尚未创建")
|
|||
|
|
|
|||
|
|
if self.game_state.active_player_id != player_id:
|
|||
|
|
raise GameEngineError("不是该玩家的回合")
|
|||
|
|
|
|||
|
|
player = self.game_state.get_player(player_id)
|
|||
|
|
|
|||
|
|
# 检查卡牌是否在手中
|
|||
|
|
if card not in player.card_manager.hand:
|
|||
|
|
raise GameEngineError("卡牌不在手牌中")
|
|||
|
|
|
|||
|
|
# 检查是否有足够的kredits
|
|||
|
|
if player.kredits < card.stats.cost:
|
|||
|
|
raise GameEngineError(f"Kredits不足: 需要{card.stats.cost},当前{player.kredits}")
|
|||
|
|
|
|||
|
|
# 检查卡牌是否可以打出
|
|||
|
|
if not card.can_be_played(self.game_state):
|
|||
|
|
raise GameEngineError("当前无法打出该卡牌")
|
|||
|
|
|
|||
|
|
# 执行卡牌效果
|
|||
|
|
success = card.play_effect(self.game_state, target_position)
|
|||
|
|
|
|||
|
|
if success:
|
|||
|
|
# 从手牌移除卡牌
|
|||
|
|
player.card_manager.play_card_from_hand(card)
|
|||
|
|
# 将卡牌放入弃牌堆
|
|||
|
|
player.card_manager.discard_card(card)
|
|||
|
|
|
|||
|
|
if self.debug_mode:
|
|||
|
|
print(f"{player.name} 打出 {card.name} (费用: {card.stats.cost})")
|
|||
|
|
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def move_unit(
|
|||
|
|
self,
|
|||
|
|
player_id: int,
|
|||
|
|
unit_id: str,
|
|||
|
|
target_position: Tuple[LineType, int]
|
|||
|
|
) -> bool:
|
|||
|
|
"""
|
|||
|
|
移动单位
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
player_id: 玩家ID
|
|||
|
|
unit_id: 单位ID
|
|||
|
|
target_position: 目标位置
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
是否移动成功
|
|||
|
|
"""
|
|||
|
|
if not self.game_state:
|
|||
|
|
raise GameEngineError("游戏尚未创建")
|
|||
|
|
|
|||
|
|
if self.game_state.active_player_id != player_id:
|
|||
|
|
raise GameEngineError("不是该玩家的回合")
|
|||
|
|
|
|||
|
|
# 使用战斗引擎执行移动
|
|||
|
|
result = self.game_state.battle_engine.move_unit(unit_id, target_position, player_id)
|
|||
|
|
|
|||
|
|
if self.debug_mode and result.success:
|
|||
|
|
print(f"{self.game_state.get_player(player_id).name} 移动单位成功")
|
|||
|
|
|
|||
|
|
return result.success
|
|||
|
|
|
|||
|
|
def attack_with_unit(
|
|||
|
|
self,
|
|||
|
|
player_id: int,
|
|||
|
|
attacker_id: str,
|
|||
|
|
target_id: str
|
|||
|
|
) -> bool:
|
|||
|
|
"""
|
|||
|
|
使用单位攻击
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
player_id: 玩家ID
|
|||
|
|
attacker_id: 攻击者单位ID
|
|||
|
|
target_id: 目标单位ID
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
是否攻击成功
|
|||
|
|
"""
|
|||
|
|
if not self.game_state:
|
|||
|
|
raise GameEngineError("游戏尚未创建")
|
|||
|
|
|
|||
|
|
if self.game_state.active_player_id != player_id:
|
|||
|
|
raise GameEngineError("不是该玩家的回合")
|
|||
|
|
|
|||
|
|
# 使用战斗引擎执行攻击
|
|||
|
|
result = self.game_state.battle_engine.attack_unit(attacker_id, target_id, player_id)
|
|||
|
|
|
|||
|
|
if result.success:
|
|||
|
|
# 检查游戏胜利条件
|
|||
|
|
self.game_state.check_win_condition()
|
|||
|
|
|
|||
|
|
if self.debug_mode:
|
|||
|
|
print(f"{self.game_state.get_player(player_id).name} 攻击成功")
|
|||
|
|
|
|||
|
|
return result.success
|
|||
|
|
|
|||
|
|
def end_turn(self, player_id: int):
|
|||
|
|
"""
|
|||
|
|
结束回合
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
player_id: 玩家ID
|
|||
|
|
"""
|
|||
|
|
if not self.game_state:
|
|||
|
|
raise GameEngineError("游戏尚未创建")
|
|||
|
|
|
|||
|
|
if self.game_state.active_player_id != player_id:
|
|||
|
|
raise GameEngineError("不是该玩家的回合")
|
|||
|
|
|
|||
|
|
self.game_state.end_turn()
|
|||
|
|
|
|||
|
|
# 检查游戏胜利条件
|
|||
|
|
self.game_state.check_win_condition()
|
|||
|
|
|
|||
|
|
def get_player_hand(self, player_id: int) -> List[BaseCard]:
|
|||
|
|
"""
|
|||
|
|
获取玩家手牌
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
player_id: 玩家ID
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
手牌列表
|
|||
|
|
"""
|
|||
|
|
if not self.game_state:
|
|||
|
|
raise GameEngineError("游戏尚未创建")
|
|||
|
|
|
|||
|
|
return self.game_state.get_player(player_id).card_manager.get_hand_copy()
|
|||
|
|
|
|||
|
|
def get_playable_cards(self, player_id: int) -> List[BaseCard]:
|
|||
|
|
"""
|
|||
|
|
获取玩家当前可以打出的卡牌
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
player_id: 玩家ID
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
可打出的卡牌列表
|
|||
|
|
"""
|
|||
|
|
if not self.game_state:
|
|||
|
|
raise GameEngineError("游戏尚未创建")
|
|||
|
|
|
|||
|
|
player = self.game_state.get_player(player_id)
|
|||
|
|
return player.card_manager.get_playable_cards(player.kredits)
|
|||
|
|
|
|||
|
|
def get_battlefield_state(self) -> Dict[str, Any]:
|
|||
|
|
"""
|
|||
|
|
获取战场状态
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
战场状态字典
|
|||
|
|
"""
|
|||
|
|
if not self.game_state:
|
|||
|
|
raise GameEngineError("游戏尚未创建")
|
|||
|
|
|
|||
|
|
battlefield = self.game_state.get_battlefield()
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
'player1_support': {
|
|||
|
|
'units': [str(unit) for unit in battlefield.player1_support.get_units()],
|
|||
|
|
'hq': str(battlefield.player1_support.get_hq()) if battlefield.player1_support.get_hq() else None
|
|||
|
|
},
|
|||
|
|
'front_line': {
|
|||
|
|
'units': [str(unit) for unit in battlefield.front_line.get_units()]
|
|||
|
|
},
|
|||
|
|
'player2_support': {
|
|||
|
|
'units': [str(unit) for unit in battlefield.player2_support.get_units()],
|
|||
|
|
'hq': str(battlefield.player2_support.get_hq()) if battlefield.player2_support.get_hq() else None
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def get_game_statistics(self) -> Dict[str, Any]:
|
|||
|
|
"""
|
|||
|
|
获取游戏统计信息
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
游戏统计信息字典
|
|||
|
|
"""
|
|||
|
|
if not self.game_state:
|
|||
|
|
return {'error': '游戏尚未创建'}
|
|||
|
|
|
|||
|
|
return self.game_state.get_game_statistics()
|
|||
|
|
|
|||
|
|
def is_game_over(self) -> bool:
|
|||
|
|
"""检查游戏是否结束"""
|
|||
|
|
return self.game_state and self.game_state.game_ended
|
|||
|
|
|
|||
|
|
def get_winner(self) -> Optional[str]:
|
|||
|
|
"""获取游戏获胜者"""
|
|||
|
|
if not self.game_state or not self.game_state.game_ended:
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
if self.game_state.winner_id is not None:
|
|||
|
|
return self.game_state.get_player(self.game_state.winner_id).name
|
|||
|
|
|
|||
|
|
return None
|