259 lines
8.6 KiB
Python
259 lines
8.6 KiB
Python
"""
|
||
卡组构建和验证系统
|
||
"""
|
||
from typing import List, Dict, Optional, Set, Tuple
|
||
from collections import defaultdict, Counter
|
||
|
||
from ..core.enums import Nation, Rarity
|
||
from .card import BaseCard, UnitCard
|
||
|
||
|
||
class DeckValidationError(Exception):
|
||
"""卡组验证错误"""
|
||
pass
|
||
|
||
|
||
class Deck:
|
||
"""卡组类"""
|
||
|
||
def __init__(
|
||
self,
|
||
major_nation: Nation,
|
||
minor_nation: Nation,
|
||
hq_card: BaseCard,
|
||
cards: List[BaseCard]
|
||
):
|
||
self.major_nation = major_nation
|
||
self.minor_nation = minor_nation
|
||
self.hq_card = hq_card
|
||
self.cards = cards.copy() # 39张正常卡牌
|
||
|
||
# 验证卡组
|
||
self._validate()
|
||
|
||
def _validate(self):
|
||
"""验证卡组的合法性"""
|
||
# 基础数量检查
|
||
if len(self.cards) != 39:
|
||
raise DeckValidationError(f"卡组必须包含39张卡牌,当前有{len(self.cards)}张")
|
||
|
||
# 国家验证
|
||
if self.major_nation not in Nation.get_majors():
|
||
raise DeckValidationError(f"主国{self.major_nation}不在允许的主要国家列表中")
|
||
|
||
if self.minor_nation not in Nation.get_all():
|
||
raise DeckValidationError(f"盟国{self.minor_nation}不是有效的国家")
|
||
|
||
if self.major_nation == self.minor_nation:
|
||
raise DeckValidationError("主国和盟国不能相同")
|
||
|
||
# 稀有度验证
|
||
self._validate_rarity_limits()
|
||
|
||
# 国家限制验证
|
||
self._validate_nation_limits()
|
||
|
||
def _validate_rarity_limits(self):
|
||
"""验证稀有度限制"""
|
||
# 按卡牌名称统计每种稀有度的卡牌数量
|
||
card_name_counts = defaultdict(int)
|
||
|
||
for card in self.cards:
|
||
card_name_counts[card.name] += 1
|
||
|
||
# 检查每种卡牌是否超过稀有度限制
|
||
for card in self.cards:
|
||
card_name = card.name
|
||
card_count = card_name_counts[card_name]
|
||
max_allowed = card.stats.rarity.max_copies_in_deck()
|
||
|
||
if card.stats.rarity == Rarity.SPECIAL:
|
||
if card_count > 0:
|
||
raise DeckValidationError("0级卡牌不能带入初始卡组")
|
||
elif card_count > max_allowed:
|
||
raise DeckValidationError(
|
||
f"卡牌'{card_name}'({card.stats.rarity})最多只能带{max_allowed}张,当前有{card_count}张"
|
||
)
|
||
|
||
# 避免重复检查同名卡牌
|
||
card_name_counts[card_name] = 0
|
||
|
||
def _validate_nation_limits(self):
|
||
"""验证国家限制"""
|
||
major_cards = 0
|
||
minor_cards = 0
|
||
invalid_cards = []
|
||
|
||
for card in self.cards:
|
||
if self._is_major_nation_card(card):
|
||
major_cards += 1
|
||
elif self._is_minor_nation_card(card):
|
||
minor_cards += 1
|
||
|
||
# 检查是否违反盟国1级卡限制
|
||
if card.stats.rarity == Rarity.ELITE:
|
||
raise DeckValidationError("不能带盟国的1级稀有度卡牌")
|
||
else:
|
||
invalid_cards.append(card)
|
||
|
||
# 检查无效卡牌
|
||
if invalid_cards:
|
||
invalid_names = [card.name for card in invalid_cards]
|
||
raise DeckValidationError(
|
||
f"以下卡牌不属于主国或盟国,无法带入卡组: {', '.join(invalid_names)}"
|
||
)
|
||
|
||
# 检查盟国卡牌数量限制
|
||
if minor_cards > 12:
|
||
raise DeckValidationError(f"盟国卡牌最多只能带12张,当前有{minor_cards}张")
|
||
|
||
# 检查总数
|
||
total_expected = 39
|
||
total_actual = major_cards + minor_cards
|
||
if total_actual != total_expected:
|
||
raise DeckValidationError(
|
||
f"卡组总数不匹配: 预期{total_expected}张,实际{total_actual}张"
|
||
)
|
||
|
||
def _is_major_nation_card(self, card: BaseCard) -> bool:
|
||
"""检查卡牌是否属于主国"""
|
||
# 原国家匹配
|
||
if card.stats.nation == self.major_nation:
|
||
return True
|
||
|
||
# 流亡国家匹配
|
||
if card.stats.exile_nations and self.major_nation in card.stats.exile_nations:
|
||
return True
|
||
|
||
return False
|
||
|
||
def _is_minor_nation_card(self, card: BaseCard) -> bool:
|
||
"""检查卡牌是否属于盟国"""
|
||
# 如果已经是主国卡,就不算盟国卡
|
||
if self._is_major_nation_card(card):
|
||
return False
|
||
|
||
# 原国家匹配
|
||
if card.stats.nation == self.minor_nation:
|
||
return True
|
||
|
||
# 流亡国家匹配
|
||
if card.stats.exile_nations and self.minor_nation in card.stats.exile_nations:
|
||
return True
|
||
|
||
return False
|
||
|
||
def get_all_cards(self) -> List[BaseCard]:
|
||
"""获取包含HQ在内的所有卡牌(40张)"""
|
||
return [self.hq_card] + self.cards
|
||
|
||
def get_deck_cards(self) -> List[BaseCard]:
|
||
"""获取抽牌堆卡牌(39张,不包括HQ)"""
|
||
return self.cards.copy()
|
||
|
||
def get_statistics(self) -> Dict:
|
||
"""获取卡组统计信息"""
|
||
stats = {
|
||
'total_cards': len(self.cards),
|
||
'major_nation': self.major_nation,
|
||
'minor_nation': self.minor_nation,
|
||
'rarity_distribution': defaultdict(int),
|
||
'nation_distribution': {'major': 0, 'minor': 0},
|
||
'cost_distribution': defaultdict(int),
|
||
'card_type_distribution': defaultdict(int)
|
||
}
|
||
|
||
for card in self.cards:
|
||
# 稀有度分布
|
||
stats['rarity_distribution'][card.stats.rarity] += 1
|
||
|
||
# 国家分布
|
||
if self._is_major_nation_card(card):
|
||
stats['nation_distribution']['major'] += 1
|
||
else:
|
||
stats['nation_distribution']['minor'] += 1
|
||
|
||
# 费用分布
|
||
stats['cost_distribution'][card.stats.cost] += 1
|
||
|
||
# 卡牌类型分布
|
||
stats['card_type_distribution'][card.card_type] += 1
|
||
|
||
return stats
|
||
|
||
|
||
class DeckBuilder:
|
||
"""卡组构建器"""
|
||
|
||
@staticmethod
|
||
def build_deck(
|
||
major_nation: Nation,
|
||
minor_nation: Nation,
|
||
cards: List[BaseCard],
|
||
hq_card: Optional[BaseCard] = None
|
||
) -> Deck:
|
||
"""构建卡组"""
|
||
|
||
# 如果没有提供HQ卡,创建默认HQ卡
|
||
if hq_card is None:
|
||
hq_card = DeckBuilder.create_default_hq_card(major_nation)
|
||
|
||
return Deck(major_nation, minor_nation, hq_card, cards)
|
||
|
||
@staticmethod
|
||
def create_default_hq_card(nation: Nation) -> BaseCard:
|
||
"""为指定国家创建默认HQ卡"""
|
||
from .card import BaseCard, CardType
|
||
|
||
# 创建一个简单的HQ卡实现
|
||
class HQCard(BaseCard):
|
||
def can_be_played(self, game_state):
|
||
return False # HQ卡不能被打出
|
||
|
||
def play_effect(self, game_state, target=None):
|
||
return False # HQ卡没有打出效果
|
||
|
||
# 根据国家确定首都名称
|
||
capital_names = {
|
||
Nation.GERMANY: "柏林",
|
||
Nation.USA: "华盛顿",
|
||
Nation.UK: "伦敦",
|
||
Nation.JAPAN: "东京",
|
||
Nation.SOVIET: "莫斯科",
|
||
Nation.FINLAND: "赫尔辛基",
|
||
Nation.POLAND: "华沙",
|
||
Nation.FRANCE: "巴黎",
|
||
Nation.ITALY: "罗马"
|
||
}
|
||
|
||
capital_name = capital_names.get(nation, "未知首都")
|
||
|
||
return HQCard(
|
||
name=f"{capital_name} HQ",
|
||
card_type=CardType.ORDER, # 临时使用ORDER类型
|
||
cost=0,
|
||
nation=nation,
|
||
rarity=Rarity.SPECIAL,
|
||
description=f"{nation}的指挥总部"
|
||
)
|
||
|
||
@staticmethod
|
||
def validate_deck_legality(
|
||
major_nation: Nation,
|
||
minor_nation: Nation,
|
||
cards: List[BaseCard]
|
||
) -> Tuple[bool, List[str]]:
|
||
"""验证卡组合法性,返回(是否合法, 错误列表)"""
|
||
errors = []
|
||
|
||
try:
|
||
# 尝试构建卡组,会自动进行验证
|
||
hq_card = DeckBuilder.create_default_hq_card(major_nation)
|
||
Deck(major_nation, minor_nation, hq_card, cards)
|
||
return True, []
|
||
except DeckValidationError as e:
|
||
errors.append(str(e))
|
||
return False, errors
|
||
except Exception as e:
|
||
errors.append(f"未知错误: {str(e)}")
|
||
return False, errors |