kards-env/tests/test_turn_restrictions.py

225 lines
7.9 KiB
Python
Raw Permalink Normal View History

2025-09-05 17:05:43 +08:00
#!/usr/bin/env python3
"""
测试回合制行动限制
- 刚部署单位不能行动除非有Blitz
- 单位一回合只能移动或攻击二选一除非有Tank
- 单位一回合最多攻击一次除非有Fury
"""
import sys
import os
# 添加项目路径
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from kards_battle.core.battle_engine import BattleEngine
from kards_battle.units.unit_loader import load_unit
from interactive.command_parser import CommandParser
def test_newly_deployed_unit_cannot_act():
"""测试刚部署的单位不能行动"""
print("=== 测试刚部署单位不能行动 ===")
engine = BattleEngine("Germany", "USA", debug_mode=True)
parser = CommandParser(engine)
# 部署一个普通单位没有BLITZ
grenadier = load_unit('ger_infantry_grenadier')
engine.deploy_unit_to_support(grenadier, 0)
engine.debug_set_kredits(0, kredits=5)
print(f"单位关键词: {grenadier.keywords}")
print(f"单位状态: deployed_this_turn={grenadier.deployed_this_turn}")
print(f" can_operate_immediately={grenadier.can_operate_immediately}")
# 尝试移动刚部署的单位
print("\n尝试移动刚部署的单位:")
success, message = parser.parse("move 1 0")
print(f"移动结果: {success} - {message}")
assert not success, "刚部署的单位应该不能移动"
assert "deployed this turn" in message, f"错误信息应该提到部署限制: {message}"
# 尝试攻击
print("\n尝试攻击:")
# 需要有目标,先部署敌军
marine = load_unit('usa_infantry_marine')
engine.deploy_unit_to_support(marine, 1)
success, message = parser.parse("attack S1 S0")
print(f"攻击结果: {success} - {message}")
assert not success, "刚部署的单位应该不能攻击"
assert "deployed this turn" in message, f"错误信息应该提到部署限制: {message}"
def test_blitz_unit_can_act_immediately():
"""测试有Blitz关键词的单位可以立即行动"""
print("\n=== 测试Blitz单位立即行动 ===")
engine = BattleEngine("Germany", "USA", debug_mode=True)
parser = CommandParser(engine)
# 部署一个有Blitz的单位
stormtrooper = load_unit('ger_infantry_stormtrooper') # 应该有BLITZ关键词
engine.deploy_unit_to_support(stormtrooper, 0)
engine.debug_set_kredits(0, kredits=5)
print(f"单位关键词: {stormtrooper.keywords}")
print(f"can_operate_immediately: {stormtrooper.can_operate_immediately}")
if stormtrooper.has_keyword("BLITZ"):
# 尝试移动Blitz单位
print("\n尝试移动Blitz单位:")
success, message = parser.parse("move 1 0")
print(f"移动结果: {success} - {message}")
assert success, f"Blitz单位应该能立即移动: {message}"
else:
print("注意: Stormtrooper没有BLITZ关键词跳过此测试")
def test_move_or_attack_restriction():
"""测试移动或攻击二选一限制"""
print("\n=== 测试移动攻击二选一 ===")
engine = BattleEngine("Germany", "USA", debug_mode=True)
parser = CommandParser(engine)
# 部署单位并让其可以行动
panzer = load_unit('ger_tank_panzer_iv') # Tank有BLITZ和移动攻击能力
engine.deploy_unit_to_support(panzer, 0)
engine.debug_set_kredits(0, kredits=10)
# 结束回合让单位状态重置
engine.end_turn() # 切换到美军
engine.end_turn() # 切换回德军,新回合开始
engine.debug_set_kredits(0, kredits=10)
print(f"单位状态: deployed_this_turn={panzer.deployed_this_turn}")
print(f" can_move_and_attack={panzer.can_move_and_attack}")
# 先移动
print("\n1. 移动单位:")
success, message = parser.parse("move 1 0")
print(f"移动结果: {success} - {message}")
if success:
print(f"移动后状态: has_moved_this_turn={panzer.has_moved_this_turn}")
# 再尝试攻击
print("\n2. 移动后尝试攻击:")
# 部署目标
marine = load_unit('usa_infantry_marine')
engine.deploy_unit_to_support(marine, 1)
success, message = parser.parse("attack F0 S0")
print(f"攻击结果: {success} - {message}")
if panzer.can_move_and_attack:
print("Tank单位应该可以移动后攻击")
else:
assert not success, "普通单位移动后应该不能攻击"
assert "has moved" in message, f"错误信息应该提到移动限制: {message}"
def test_multiple_attack_restriction():
"""测试多次攻击限制"""
print("\n=== 测试攻击次数限制 ===")
engine = BattleEngine("Germany", "USA", debug_mode=True)
parser = CommandParser(engine)
# 部署攻击单位
grenadier = load_unit('ger_infantry_grenadier')
engine.deploy_unit_to_support(grenadier, 0)
engine.debug_set_kredits(0, kredits=20)
# 部署多个目标
for i in range(3):
marine = load_unit('usa_infantry_marine')
engine.deploy_unit_to_support(marine, 1)
# 结束回合让单位可以行动
engine.end_turn() # 切换到美军
engine.end_turn() # 切换回德军,新回合开始
engine.debug_set_kredits(0, kredits=20)
print(f"最大攻击次数: {grenadier.max_attacks_per_turn}")
# 第一次攻击
print("\n1. 第一次攻击:")
success, message = parser.parse("attack S1 S0")
print(f"攻击结果: {success} - {message}")
if success:
print(f"攻击次数: {grenadier.attacks_this_turn}")
# 第二次攻击
print("\n2. 第二次攻击:")
success, message = parser.parse("attack S1 S1")
print(f"攻击结果: {success} - {message}")
if grenadier.can_attack_multiple_times:
print("有Fury等能力的单位可以多次攻击")
else:
assert not success, "普通单位应该不能攻击两次"
assert "maximum attacks" in message, f"错误信息应该提到攻击次数限制: {message}"
def test_tank_abilities():
"""测试Tank类单位的特殊能力"""
print("\n=== 测试Tank单位特殊能力 ===")
engine = BattleEngine("Germany", "USA", debug_mode=True)
parser = CommandParser(engine)
# 部署Tank单位
panzer = load_unit('ger_tank_panzer_iv')
engine.deploy_unit_to_support(panzer, 0)
engine.debug_set_kredits(0, kredits=20)
# 部署目标
marine = load_unit('usa_infantry_marine')
engine.deploy_unit_to_support(marine, 1)
# 结束回合让单位可以行动
engine.end_turn() # 切换到美军
engine.end_turn() # 切换回德军,新回合开始
engine.debug_set_kredits(0, kredits=20)
print(f"Tank能力: can_move_and_attack={panzer.can_move_and_attack}")
print(f"单位类型: {panzer.unit_type}")
if panzer.can_move_and_attack:
# Tank应该可以移动后攻击
print("\n1. Tank移动:")
success, message = parser.parse("move 1 0")
print(f"移动结果: {success} - {message}")
if success:
print("\n2. Tank移动后攻击:")
success, message = parser.parse("attack F0 S0")
print(f"攻击结果: {success} - {message}")
assert success, f"Tank应该能移动后攻击: {message}"
if __name__ == "__main__":
print("开始回合制限制测试\n")
tests = [
test_newly_deployed_unit_cannot_act,
test_blitz_unit_can_act_immediately,
test_move_or_attack_restriction,
test_multiple_attack_restriction,
test_tank_abilities,
]
for test in tests:
try:
test()
print("✅ 测试通过")
except AssertionError as e:
print(f"❌ 测试失败: {e}")
except Exception as e:
print(f"❌ 测试异常: {e}")
print("-" * 50)
print("\n回合制限制测试完成")