276 lines
10 KiB
Python
276 lines
10 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
全面移动系统测试 - 使用pytest
|
||
测试所有移动场景和边界条件
|
||
"""
|
||
import pytest
|
||
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.examples.sample_units import create_german_infantry, create_american_gi
|
||
from kards_battle.core.enums import LineType
|
||
|
||
|
||
class TestMovementScenarios:
|
||
"""测试移动场景"""
|
||
|
||
def setup_method(self):
|
||
"""每个测试前的设置"""
|
||
self.engine = BattleEngine("Germany", "USA", debug_mode=True)
|
||
|
||
def _deploy_and_wait(self, unit, player_id):
|
||
"""部署单位并等待一回合让其可以移动"""
|
||
deploy_result = self.engine.deploy_unit_to_support(unit, player_id)
|
||
assert deploy_result['success']
|
||
|
||
# 结束回合让单位可以移动
|
||
self.engine.end_turn()
|
||
self.engine.end_turn()
|
||
|
||
return deploy_result
|
||
|
||
def test_move_to_empty_frontline_occupies_control(self):
|
||
"""测试:移向空的前线占领前线"""
|
||
# 部署德军步兵到支援线
|
||
unit = create_german_infantry()
|
||
unit.stats.operation_cost = 1
|
||
self._deploy_and_wait(unit, 0)
|
||
|
||
# 设置足够的Kredits
|
||
self.engine.debug_set_kredits(0, kredits=5)
|
||
|
||
# 移动到空的前线
|
||
move_result = self.engine.move_unit(unit.id, (LineType.FRONT, 0), 0)
|
||
|
||
assert move_result['success']
|
||
assert move_result['action'] == 'move_to_front'
|
||
assert move_result['front_line_controller'] == 'Germany' # 德军控制前线
|
||
|
||
# 验证战场状态
|
||
front_units = self.engine.battlefield.front_line.get_all_units()
|
||
assert len(front_units) == 1
|
||
assert front_units[0].id == unit.id
|
||
|
||
def test_move_to_friendly_frontline_empty_position(self):
|
||
"""测试:移向有己方的前线,进入空格"""
|
||
# 部署两个德军单位
|
||
unit1 = create_german_infantry()
|
||
unit1.name = "Infantry1"
|
||
unit1.stats.operation_cost = 1
|
||
unit2 = create_german_infantry()
|
||
unit2.name = "Infantry2"
|
||
unit2.stats.operation_cost = 1
|
||
|
||
self.engine.deploy_unit_to_support(unit1, 0)
|
||
self.engine.deploy_unit_to_support(unit2, 0)
|
||
|
||
self.engine.debug_set_kredits(0, kredits=10)
|
||
|
||
# 先移动unit1到前线
|
||
self.engine.move_unit(unit1.id, (LineType.FRONT, 0), 0)
|
||
|
||
# 再移动unit2到前线空位
|
||
move_result = self.engine.move_unit(unit2.id, (LineType.FRONT, 1), 0)
|
||
|
||
assert move_result['success']
|
||
assert move_result['to_position'] == 1
|
||
|
||
# 验证前线有两个单位
|
||
front_units = self.engine.battlefield.front_line.get_all_units()
|
||
assert len(front_units) == 2
|
||
|
||
def test_move_to_friendly_frontline_squeeze_position(self):
|
||
"""测试:移向有己方的前线,挤占已有位置"""
|
||
# 部署两个德军单位
|
||
unit1 = create_german_infantry()
|
||
unit1.name = "Infantry1"
|
||
unit1.stats.operation_cost = 1
|
||
unit2 = create_german_infantry()
|
||
unit2.name = "Infantry2"
|
||
unit2.stats.operation_cost = 1
|
||
|
||
self.engine.deploy_unit_to_support(unit1, 0)
|
||
self.engine.deploy_unit_to_support(unit2, 0)
|
||
|
||
self.engine.debug_set_kredits(0, kredits=10)
|
||
|
||
# 先移动unit1到前线位置0
|
||
self.engine.move_unit(unit1.id, (LineType.FRONT, 0), 0)
|
||
|
||
# 再移动unit2到位置0,应该挤入,unit1后移
|
||
move_result = self.engine.move_unit(unit2.id, (LineType.FRONT, 0), 0)
|
||
|
||
assert move_result['success']
|
||
assert move_result['to_position'] == 0
|
||
|
||
# 验证unit2在位置0,unit1在位置1
|
||
front_units = self.engine.battlefield.front_line.get_all_units()
|
||
assert len(front_units) == 2
|
||
assert front_units[0].name == "Infantry2" # unit2挤到前面
|
||
assert front_units[1].name == "Infantry1" # unit1被挤到后面
|
||
|
||
def test_move_from_frontline_to_enemy_support_fails(self):
|
||
"""测试:前线移向敌方阵线(应失败,局面不变)"""
|
||
# 部署并移动德军到前线
|
||
unit = create_german_infantry()
|
||
unit.stats.operation_cost = 1
|
||
|
||
self.engine.deploy_unit_to_support(unit, 0)
|
||
self.engine.debug_set_kredits(0, kredits=10)
|
||
self.engine.move_unit(unit.id, (LineType.FRONT, 0), 0)
|
||
|
||
# 尝试从前线移动到敌方支援线(不允许)
|
||
move_result = self.engine.move_unit(unit.id, (LineType.PLAYER2_SUPPORT, 0), 0)
|
||
|
||
assert not move_result['success']
|
||
assert "Can only move to front line" in move_result['reason']
|
||
|
||
# 验证单位仍在前线
|
||
front_units = self.engine.battlefield.front_line.get_all_units()
|
||
assert len(front_units) == 1
|
||
assert front_units[0].id == unit.id
|
||
|
||
def test_move_to_full_frontline_fails(self):
|
||
"""测试:前线已满时移向前线(应失败)"""
|
||
self.engine.debug_set_kredits(0, kredits=20)
|
||
|
||
# 部署并移动5个单位到前线(填满前线)
|
||
units = []
|
||
for i in range(5):
|
||
unit = create_german_infantry()
|
||
unit.name = f"Infantry{i+1}"
|
||
unit.stats.operation_cost = 1
|
||
units.append(unit)
|
||
|
||
self.engine.deploy_unit_to_support(unit, 0)
|
||
self.engine.move_unit(unit.id, (LineType.FRONT, i), 0)
|
||
|
||
# 验证前线已满
|
||
assert self.engine.battlefield.front_line.is_full()
|
||
|
||
# 尝试部署第6个单位并移动到前线
|
||
extra_unit = create_german_infantry()
|
||
extra_unit.name = "ExtraInfantry"
|
||
extra_unit.stats.operation_cost = 1
|
||
|
||
self.engine.deploy_unit_to_support(extra_unit, 0)
|
||
move_result = self.engine.move_unit(extra_unit.id, (LineType.FRONT, 2), 0)
|
||
|
||
assert not move_result['success']
|
||
assert "full" in move_result['reason'].lower()
|
||
|
||
# 验证前线仍然只有5个单位
|
||
front_units = self.engine.battlefield.front_line.get_all_units()
|
||
assert len(front_units) == 5
|
||
|
||
def test_move_to_enemy_controlled_frontline_fails(self):
|
||
"""测试:前线有敌人时移向前线空地(应失败)"""
|
||
# 先让美军占领前线
|
||
usa_unit = create_american_gi()
|
||
usa_unit.stats.operation_cost = 1
|
||
|
||
# 切换到美军回合
|
||
self.engine.end_turn() # 切换到美军
|
||
|
||
self.engine.deploy_unit_to_support(usa_unit, 1)
|
||
self.engine.debug_set_kredits(1, kredits=5)
|
||
usa_move = self.engine.move_unit(usa_unit.id, (LineType.FRONT, 0), 1)
|
||
assert usa_move['success']
|
||
assert usa_move['front_line_controller'] == 'USA'
|
||
|
||
# 切换回德军回合
|
||
self.engine.end_turn() # 切换回德军
|
||
|
||
# 德军尝试移动到被美军控制的前线
|
||
ger_unit = create_german_infantry()
|
||
ger_unit.stats.operation_cost = 1
|
||
|
||
self.engine.deploy_unit_to_support(ger_unit, 0)
|
||
self.engine.debug_set_kredits(0, kredits=5)
|
||
|
||
# 尝试移动到前线空位(位置1)
|
||
move_result = self.engine.move_unit(ger_unit.id, (LineType.FRONT, 1), 0)
|
||
|
||
assert not move_result['success']
|
||
assert "controlled by enemy" in move_result['reason'].lower()
|
||
|
||
# 验证前线仍然只有美军单位
|
||
front_units = self.engine.battlefield.front_line.get_all_units()
|
||
assert len(front_units) == 1
|
||
assert front_units[0].owner == 'USA'
|
||
|
||
def test_units_cannot_move_within_frontline(self):
|
||
"""测试:前线单位不能在前线内移动"""
|
||
# 部署并移动德军到前线
|
||
unit = create_german_infantry()
|
||
unit.stats.operation_cost = 1
|
||
|
||
self.engine.deploy_unit_to_support(unit, 0)
|
||
self.engine.debug_set_kredits(0, kredits=10)
|
||
self.engine.move_unit(unit.id, (LineType.FRONT, 0), 0)
|
||
|
||
# 尝试在前线内移动(从位置0到位置1)
|
||
move_result = self.engine.move_unit(unit.id, (LineType.FRONT, 1), 0)
|
||
|
||
assert not move_result['success']
|
||
assert "Units on front line cannot move" in move_result['reason']
|
||
|
||
# 验证单位仍在原位置
|
||
front_units = self.engine.battlefield.front_line.get_all_units()
|
||
assert len(front_units) == 1
|
||
assert front_units[0].position == (LineType.FRONT, 0)
|
||
|
||
def test_insufficient_kredits_move_fails(self):
|
||
"""测试:Kredits不足时移动失败"""
|
||
unit = create_german_infantry()
|
||
unit.stats.operation_cost = 3 # 需要3点激活费用
|
||
|
||
self.engine.deploy_unit_to_support(unit, 0)
|
||
# 只给1点Kredits
|
||
self.engine.debug_set_kredits(0, kredits=1)
|
||
|
||
move_result = self.engine.move_unit(unit.id, (LineType.FRONT, 0), 0)
|
||
|
||
assert not move_result['success']
|
||
assert "Insufficient Kredits" in move_result['reason']
|
||
|
||
# 验证单位仍在支援线
|
||
support_units = self.engine.battlefield.player1_support.get_all_units()
|
||
assert len(support_units) == 1
|
||
|
||
def test_move_consumes_kredits(self):
|
||
"""测试:移动消耗Kredits"""
|
||
unit = create_german_infantry()
|
||
unit.stats.operation_cost = 2
|
||
|
||
self.engine.deploy_unit_to_support(unit, 0)
|
||
self.engine.debug_set_kredits(0, kredits=5)
|
||
|
||
initial_kredits = self.engine.get_kredits(0)
|
||
move_result = self.engine.move_unit(unit.id, (LineType.FRONT, 0), 0)
|
||
final_kredits = self.engine.get_kredits(0)
|
||
|
||
assert move_result['success']
|
||
assert final_kredits == initial_kredits - 2
|
||
|
||
def test_not_your_turn_move_fails(self):
|
||
"""测试:不是自己回合时移动失败"""
|
||
unit = create_german_infantry()
|
||
unit.stats.operation_cost = 1
|
||
|
||
self.engine.deploy_unit_to_support(unit, 0)
|
||
|
||
# 切换到美军回合
|
||
self.engine.end_turn()
|
||
|
||
# 德军在美军回合尝试移动
|
||
move_result = self.engine.move_unit(unit.id, (LineType.FRONT, 0), 0)
|
||
|
||
assert not move_result['success']
|
||
assert "Not your turn" in move_result['reason']
|
||
|
||
|
||
if __name__ == "__main__":
|
||
pytest.main([__file__, "-v"]) |