245 lines
8.5 KiB
Python
245 lines
8.5 KiB
Python
"""
|
|
测试事件系统和烟幕管理器
|
|
"""
|
|
import pytest
|
|
from kards_battle.core.battle_engine import BattleEngine
|
|
from kards_battle.units.unit_loader import load_unit
|
|
from kards_battle.core.enums import LineType
|
|
from kards_battle.events.event_system import (
|
|
EventType, GameEvent, EventBus, EventSubscriber,
|
|
publish_event, subscribe_to_events
|
|
)
|
|
from kards_battle.events.managers.smokescreen_manager import SmokescreenManager
|
|
|
|
|
|
class MockEventSubscriber(EventSubscriber):
|
|
"""测试用事件订阅者"""
|
|
|
|
def __init__(self):
|
|
self.received_events = []
|
|
|
|
def get_subscribed_events(self):
|
|
return [EventType.UNIT_DEPLOYED, EventType.UNIT_MOVED, EventType.UNIT_ATTACKED]
|
|
|
|
def handle_event(self, event):
|
|
self.received_events.append(event)
|
|
|
|
|
|
class TestEventSystem:
|
|
"""事件系统测试"""
|
|
|
|
def test_event_bus_basic_functionality(self):
|
|
"""测试事件总线基本功能"""
|
|
bus = EventBus()
|
|
subscriber = MockEventSubscriber()
|
|
|
|
# 订阅事件
|
|
bus.subscribe(subscriber)
|
|
assert bus.get_subscriber_count(EventType.UNIT_DEPLOYED) == 1
|
|
|
|
# 发布事件
|
|
event = GameEvent(EventType.UNIT_DEPLOYED, data={"test": "data"})
|
|
bus.publish(event)
|
|
|
|
# 检查是否收到事件
|
|
assert len(subscriber.received_events) == 1
|
|
assert subscriber.received_events[0].event_type == EventType.UNIT_DEPLOYED
|
|
assert subscriber.received_events[0].data["test"] == "data"
|
|
|
|
def test_event_cancellation(self):
|
|
"""测试事件取消功能"""
|
|
bus = EventBus()
|
|
|
|
class CancellingSubscriber(EventSubscriber):
|
|
def get_subscribed_events(self):
|
|
return [EventType.BEFORE_ATTACK_CHECK]
|
|
|
|
def handle_event(self, event):
|
|
if event.cancellable:
|
|
event.cancel("Test cancellation")
|
|
|
|
subscriber = CancellingSubscriber()
|
|
bus.subscribe(subscriber)
|
|
|
|
# 发布可取消事件
|
|
event = GameEvent(
|
|
EventType.BEFORE_ATTACK_CHECK,
|
|
cancellable=True
|
|
)
|
|
bus.publish(event)
|
|
|
|
# 检查事件是否被取消
|
|
assert event.cancelled
|
|
assert event.cancel_reason == "Test cancellation"
|
|
|
|
|
|
class TestSmokescreenManager:
|
|
"""烟幕管理器测试"""
|
|
|
|
def setup_method(self):
|
|
"""每个测试前的设置"""
|
|
self.engine = BattleEngine('Germany', 'USA', debug_mode=True)
|
|
|
|
def test_smokescreen_deployment_and_activation(self):
|
|
"""测试烟幕部署和激活"""
|
|
unit = load_unit('ger_infantry_grenadier')
|
|
unit.add_keyword('SMOKESCREEN')
|
|
|
|
# 部署到支援线应该激活烟幕
|
|
self.engine.deploy_unit_to_support(unit, 0)
|
|
|
|
assert unit.has_keyword('SMOKESCREEN')
|
|
assert unit.position[0] == LineType.PLAYER1_SUPPORT
|
|
|
|
def test_smokescreen_removed_on_move(self):
|
|
"""测试移动时移除烟幕"""
|
|
unit = load_unit('ger_infantry_grenadier')
|
|
unit.add_keyword('SMOKESCREEN')
|
|
|
|
self.engine.deploy_unit_to_support(unit, 0)
|
|
assert unit.has_keyword('SMOKESCREEN')
|
|
|
|
# 模拟下一回合允许移动
|
|
unit.start_new_turn()
|
|
self.engine.debug_set_kredits(0, kredits=5)
|
|
|
|
# 移动到前线应该移除烟幕
|
|
result = self.engine.move_unit(unit.id, (LineType.FRONT, 0), 0)
|
|
|
|
assert result['success']
|
|
assert not unit.has_keyword('SMOKESCREEN')
|
|
|
|
def test_smokescreen_removed_on_attack(self):
|
|
"""测试攻击时移除烟幕"""
|
|
attacker = load_unit('ger_infantry_grenadier')
|
|
attacker.add_keyword('SMOKESCREEN')
|
|
target = load_unit('usa_infantry_gi')
|
|
|
|
# 部署单位
|
|
self.engine.deploy_unit_to_support(attacker, 0)
|
|
self.engine.end_turn()
|
|
self.engine.deploy_unit_to_support(target, 1)
|
|
|
|
# 移动攻击者到前线
|
|
attacker.start_new_turn()
|
|
self.engine.debug_set_kredits(0, kredits=5)
|
|
self.engine.move_unit(attacker.id, (LineType.FRONT, 0), 0)
|
|
|
|
# 重新添加烟幕(因为移动时被移除了)
|
|
attacker.add_keyword('SMOKESCREEN')
|
|
assert attacker.has_keyword('SMOKESCREEN')
|
|
|
|
# 切换回德军回合并攻击
|
|
self.engine.end_turn()
|
|
attacker.start_new_turn()
|
|
result = self.engine.attack_target(attacker.id, target.id, 0)
|
|
|
|
if result['success']:
|
|
# 如果攻击成功,烟幕应该被移除
|
|
assert not attacker.has_keyword('SMOKESCREEN')
|
|
|
|
def test_smokescreen_blocks_attacks(self):
|
|
"""测试烟幕阻止攻击"""
|
|
defender = load_unit('ger_infantry_grenadier')
|
|
defender.add_keyword('SMOKESCREEN')
|
|
attacker = load_unit('usa_infantry_gi')
|
|
|
|
# 部署单位
|
|
self.engine.deploy_unit_to_support(defender, 0)
|
|
self.engine.end_turn()
|
|
self.engine.deploy_unit_to_support(attacker, 1)
|
|
|
|
# 移动攻击者到前线
|
|
attacker.start_new_turn()
|
|
self.engine.debug_set_kredits(1, kredits=5)
|
|
self.engine.move_unit(attacker.id, (LineType.FRONT, 0), 1)
|
|
|
|
# 尝试攻击有烟幕的单位
|
|
attacker.start_new_turn()
|
|
result = self.engine.attack_target(attacker.id, defender.id, 1)
|
|
|
|
assert not result['success']
|
|
assert "Protected by SMOKESCREEN" in result['reason']
|
|
assert defender.has_keyword('SMOKESCREEN') # 烟幕应该还在
|
|
|
|
def test_smokescreen_removed_on_front_line(self):
|
|
"""测试单位在前线时失去烟幕"""
|
|
unit = load_unit('ger_infantry_grenadier')
|
|
unit.add_keyword('SMOKESCREEN')
|
|
|
|
self.engine.deploy_unit_to_support(unit, 0)
|
|
assert unit.has_keyword('SMOKESCREEN')
|
|
|
|
# 移动到前线
|
|
unit.start_new_turn()
|
|
self.engine.debug_set_kredits(0, kredits=5)
|
|
result = self.engine.move_unit(unit.id, (LineType.FRONT, 0), 0)
|
|
|
|
assert result['success']
|
|
assert unit.position[0] == LineType.FRONT
|
|
assert not unit.has_keyword('SMOKESCREEN')
|
|
|
|
def test_smokescreen_removed_with_guard(self):
|
|
"""测试获得GUARD关键词时失去烟幕"""
|
|
unit = load_unit('ger_infantry_grenadier')
|
|
unit.add_keyword('SMOKESCREEN')
|
|
|
|
self.engine.deploy_unit_to_support(unit, 0)
|
|
assert unit.has_keyword('SMOKESCREEN')
|
|
|
|
# 添加GUARD关键词应该移除烟幕
|
|
unit.add_keyword('GUARD')
|
|
|
|
# 发布关键词添加事件来触发管理器
|
|
publish_event(GameEvent(
|
|
event_type=EventType.KEYWORD_ADDED,
|
|
target=unit,
|
|
data={'keyword': 'GUARD'}
|
|
))
|
|
|
|
# 烟幕应该被移除(可能需要等待事件处理)
|
|
# 这个测试可能需要调整,取决于事件处理的具体实现
|
|
|
|
|
|
class TestIntegratedEventSystem:
|
|
"""集成事件系统测试"""
|
|
|
|
def setup_method(self):
|
|
"""每个测试前的设置"""
|
|
self.engine = BattleEngine('Germany', 'USA', debug_mode=True)
|
|
|
|
def test_event_system_deployment_and_movement(self):
|
|
"""测试事件系统的部署和移动事件发布"""
|
|
subscriber = MockEventSubscriber()
|
|
subscribe_to_events(subscriber)
|
|
|
|
# 创建和部署单位
|
|
ger_unit = load_unit('ger_infantry_grenadier')
|
|
|
|
self.engine.deploy_unit_to_support(ger_unit, 0)
|
|
|
|
# 检查部署事件
|
|
deployed_events = [e for e in subscriber.received_events
|
|
if e.event_type == EventType.UNIT_DEPLOYED]
|
|
assert len(deployed_events) == 1
|
|
assert deployed_events[0].source == ger_unit
|
|
|
|
# 移动单位(在新回合)
|
|
ger_unit.start_new_turn()
|
|
self.engine.debug_set_kredits(0, kredits=5)
|
|
result = self.engine.move_unit(ger_unit.id, (LineType.FRONT, 0), 0)
|
|
|
|
# 检查移动是否成功
|
|
assert result['success']
|
|
|
|
# 检查移动事件
|
|
moved_events = [e for e in subscriber.received_events
|
|
if e.event_type == EventType.UNIT_MOVED]
|
|
assert len(moved_events) == 1
|
|
assert moved_events[0].source == ger_unit
|
|
|
|
# 验证事件数据完整性
|
|
move_event = moved_events[0]
|
|
assert 'old_position' in move_event.data
|
|
assert 'new_position' in move_event.data
|
|
assert 'player_id' in move_event.data |