kards-env/tests/test_card_system.py

295 lines
11 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.

"""
卡牌系统测试
"""
import pytest
from kards_battle.core.enums import Nation, Rarity
from kards_battle.cards.card import UnitCard
from kards_battle.cards.deck import DeckBuilder, DeckValidationError
from kards_battle.cards.card_manager import CardManager
from kards_battle.cards.placeholder_cards import create_placeholder_unit_cards, create_test_deck_cards
from kards_battle.game.game_engine import GameEngine
class TestCardSystem:
"""卡牌系统基础测试"""
def test_unit_card_creation(self):
"""测试单位卡牌创建"""
card = UnitCard(
name="德军掷弹兵",
cost=2,
nation=Nation.GERMANY,
rarity=Rarity.COMMON,
unit_definition_id="ger_infantry_grenadier",
description="基础德军步兵单位"
)
assert card.name == "德军掷弹兵"
assert card.stats.cost == 2
assert card.stats.nation == Nation.GERMANY
assert card.stats.rarity == Rarity.COMMON
assert card.unit_definition_id == "ger_infantry_grenadier"
def test_placeholder_cards_creation(self):
"""测试占位卡牌创建"""
cards = create_placeholder_unit_cards()
assert len(cards) == 10
# 检查所有卡牌都是德国的
for card in cards:
assert card.stats.nation == Nation.GERMANY
assert card.stats.rarity == Rarity.COMMON
assert card.unit_definition_id == "ger_infantry_grenadier"
def test_deck_validation_success(self):
"""测试卡组验证成功案例"""
cards = create_test_deck_cards(Nation.GERMANY, Nation.ITALY)
# 应该能成功创建卡组
deck = DeckBuilder.build_deck(Nation.GERMANY, Nation.ITALY, cards)
assert deck.major_nation == Nation.GERMANY
assert deck.minor_nation == Nation.ITALY
assert len(deck.cards) == 39
# 获取统计信息
stats = deck.get_statistics()
assert stats['total_cards'] == 39
assert stats['major_nation'] == Nation.GERMANY
assert stats['minor_nation'] == Nation.ITALY
def test_deck_validation_invalid_count(self):
"""测试卡组验证:卡牌数量错误"""
cards = create_placeholder_unit_cards()[:5] # 只有5张卡
with pytest.raises(DeckValidationError, match="卡组必须包含39张卡牌"):
DeckBuilder.build_deck(Nation.GERMANY, Nation.ITALY, cards)
def test_deck_validation_invalid_major_nation(self):
"""测试卡组验证:无效主国"""
cards = create_test_deck_cards(Nation.GERMANY, Nation.ITALY)
with pytest.raises(DeckValidationError, match="主国.*不在允许的主要国家列表中"):
DeckBuilder.build_deck(Nation.FINLAND, Nation.ITALY, cards) # Finland不是主要国家
def test_deck_validation_same_nations(self):
"""测试卡组验证:主国和盟国相同"""
cards = create_test_deck_cards(Nation.GERMANY, Nation.GERMANY)
with pytest.raises(DeckValidationError, match="主国和盟国不能相同"):
DeckBuilder.build_deck(Nation.GERMANY, Nation.GERMANY, cards)
def test_card_manager_initialization(self):
"""测试卡牌管理器初始化"""
cards = create_test_deck_cards(Nation.GERMANY, Nation.ITALY)
deck = DeckBuilder.build_deck(Nation.GERMANY, Nation.ITALY, cards)
manager = CardManager(deck)
assert manager.cards_remaining_in_deck() == 39
assert manager.hand_size() == 0
assert len(manager.discard_pile) == 0
assert manager.fatigue_damage == 1
assert not manager.strategic_deployment_completed
def test_card_manager_initial_draw(self):
"""测试初始摸牌"""
cards = create_test_deck_cards(Nation.GERMANY, Nation.ITALY)
deck = DeckBuilder.build_deck(Nation.GERMANY, Nation.ITALY, cards)
manager = CardManager(deck)
drawn_cards = manager.initial_draw(5)
assert len(drawn_cards) == 5
assert manager.hand_size() == 5
assert manager.cards_remaining_in_deck() == 34
def test_card_manager_strategic_deployment(self):
"""测试战略调度"""
cards = create_test_deck_cards(Nation.GERMANY, Nation.ITALY)
deck = DeckBuilder.build_deck(Nation.GERMANY, Nation.ITALY, cards)
manager = CardManager(deck)
initial_cards = manager.initial_draw(4)
# 选择重抽2张牌
cards_to_mulligan = initial_cards[:2]
new_cards = manager.strategic_deployment(cards_to_mulligan)
assert len(new_cards) == 2
assert manager.hand_size() == 4 # 仍然是4张牌
assert manager.strategic_deployment_completed
# 不应该能再次进行战略调度
with pytest.raises(ValueError, match="战略调度已经完成"):
manager.strategic_deployment([])
def test_card_manager_fatigue_system(self):
"""测试疲劳系统"""
# 创建一个小卡组用于快速测试疲劳
small_cards = []
# 主国卡27张
for i in range(9): # 9种不同的卡
for j in range(3): # 每种3张
card = UnitCard(
name=f"德军测试卡{i}",
cost=1,
nation=Nation.GERMANY,
rarity=Rarity.COMMON,
unit_definition_id="ger_infantry_grenadier",
description="测试用德军卡牌"
)
small_cards.append(card)
# 盟国卡12张
for i in range(4): # 4种不同的卡
for j in range(3): # 每种3张
card = UnitCard(
name=f"意军测试卡{i}",
cost=1,
nation=Nation.ITALY,
rarity=Rarity.COMMON,
unit_definition_id="ger_infantry_grenadier",
description="测试用意军卡牌"
)
small_cards.append(card)
deck = DeckBuilder.build_deck(Nation.GERMANY, Nation.ITALY, small_cards)
manager = CardManager(deck)
# 抽完所有牌
while manager.can_draw_safely():
manager.draw_card()
assert manager.cards_remaining_in_deck() == 0
# 记录疲劳伤害
fatigue_damages = []
def hq_damage_callback(damage):
fatigue_damages.append(damage)
# 继续抽牌应该造成疲劳伤害
result = manager.draw_card(hq_damage_callback)
assert result is None
assert len(fatigue_damages) == 1
assert fatigue_damages[0] == 1
assert manager.fatigue_damage == 2 # 递增
# 再次抽牌
result = manager.draw_card(hq_damage_callback)
assert result is None
assert len(fatigue_damages) == 2
assert fatigue_damages[1] == 2
assert manager.fatigue_damage == 3
class TestGameEngine:
"""游戏引擎测试"""
def test_game_engine_creation(self):
"""测试游戏引擎创建"""
engine = GameEngine(debug_mode=True)
game_state = engine.create_test_game(
"Player1", Nation.GERMANY, Nation.ITALY,
"Player2", Nation.USA, Nation.UK
)
assert game_state is not None
assert game_state.player1.name == "Player1"
assert game_state.player2.name == "Player2"
assert game_state.player1.major_nation == Nation.GERMANY
assert game_state.player1.minor_nation == Nation.ITALY
assert game_state.player2.major_nation == Nation.USA
assert game_state.player2.minor_nation == Nation.UK
def test_strategic_deployment_phase(self):
"""测试战略调度阶段"""
engine = GameEngine(debug_mode=True)
game_state = engine.create_test_game()
# 初始阶段应该是战略调度
from kards_battle.game.game_state import GameStatePhase
assert game_state.phase == GameStatePhase.STRATEGIC_DEPLOYMENT
# 玩家应该可以进行战略调度
assert game_state.can_perform_strategic_deployment(0)
assert game_state.can_perform_strategic_deployment(1)
# 玩家1进行战略调度不重抽任何牌
player1_hand = game_state.player1.card_manager.get_hand_copy()
new_cards = engine.perform_strategic_deployment(0, [])
assert len(new_cards) == 0
assert not game_state.can_perform_strategic_deployment(0)
# 玩家2进行战略调度重抽1张牌
player2_hand = game_state.player2.card_manager.get_hand_copy()
cards_to_mulligan = [player2_hand[0]]
new_cards = engine.perform_strategic_deployment(1, cards_to_mulligan)
assert len(new_cards) == 1
assert not game_state.can_perform_strategic_deployment(1)
# 现在应该可以开始正式游戏
engine.start_main_game()
assert game_state.phase == GameStatePhase.GAME_ACTIVE
def test_game_flow(self):
"""测试基本游戏流程"""
engine = GameEngine(debug_mode=True)
game_state = engine.create_test_game()
# 跳过战略调度,直接开始游戏
engine.start_main_game()
# 检查初始状态
assert game_state.current_turn == 1
assert game_state.active_player_id == 0 # 先手
# 当前玩家应该有kredits
current_player = game_state.get_current_player()
assert current_player.kredits > 0
assert current_player.kredits_slot > 0
# 获取可打出的卡牌
playable_cards = engine.get_playable_cards(0)
# 第一回合可能没有可打出的卡牌,这是正常的
assert isinstance(playable_cards, list)
# 结束回合
engine.end_turn(0)
# 应该轮到玩家2
assert game_state.active_player_id == 1
# 玩家2也应该有kredits
player2 = game_state.get_current_player()
assert player2.kredits > 0
def test_card_playing(self):
"""测试打牌功能"""
engine = GameEngine(debug_mode=True)
game_state = engine.create_test_game()
engine.start_main_game()
# 获取当前玩家的可打出卡牌
current_player_id = game_state.active_player_id
playable_cards = engine.get_playable_cards(current_player_id)
if playable_cards:
# 尝试打出一张单位卡
for card in playable_cards:
if hasattr(card, 'unit_definition_id'): # 是单位卡
initial_kredits = game_state.get_current_player().kredits
success = engine.play_unit_card(current_player_id, card)
if success:
# 检查kredits是否扣除
final_kredits = game_state.get_current_player().kredits
assert final_kredits == initial_kredits - card.stats.cost
# 检查卡牌是否从手牌移除
current_hand = engine.get_player_hand(current_player_id)
assert card not in current_hand
break