kards-env/tests/test_turn_restrictions.py

225 lines
7.9 KiB
Python
Raw Permalink 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.

#!/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回合制限制测试完成")