Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add unit tests for movement and vision costs
Includes tests for changing the terrain costs, and aliased terrains, (cherry picked from commit 358f564)
- Loading branch information
1 parent
efd7905
commit aa9ff15
Showing
3 changed files
with
396 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Xv, Xv, Xv, Xv, Xv, Xv, Xv | ||
Xv, Xv, Xv, Xv, Xv, Xv, Xv | ||
Xv, Xv, destination Ce, Wwf^Fpa, Cme, Xv, Xv | ||
Xv, Xv, Xv, Xv, Wwf, Xv, Xv | ||
Xv, Xv, Uh^Fda, Wo^Bw/r, Xv, Xv, Xv | ||
Xv, Xv, Gg^Fda, Xv, Xv, Xv, Xv | ||
Xv, Xv, Xv, Dd^Ftd, Uh, Xv, Xv | ||
Xv, Xv, Xv, Xv, Hh, Xv, Xv | ||
Xv, Xv, Xv, Hh^Fds, Xv, Xv, Xv | ||
Xv, Xv, Gg, Gg^Fds, Gg, Xv, Xv | ||
Xv, Xv, 1 Gg, Xv, 2 Gg, Xv, Xv | ||
Xv, Xv, Xv, Xv, Xv, Xv, Xv | ||
Xv, Xv, Xv, Xv, Xv, Xv, Xv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,362 @@ | ||
# This series of tests checks that the C++ movetype class handles changes to movetypes correctly. | ||
|
||
# The map defines a location_id "destination", and from both start points the path to it is | ||
# Flat | ||
# Forest | ||
# Forest Hills | ||
# Hills | ||
# Cave Hills | ||
# Forest Sand | ||
# Flat Frozen Forest | ||
# Cave Hills Frozen Forest | ||
# bridge over deep water (best-of Flat and Deep Water) | ||
# ford (best-of Flat and Water) | ||
# aquatic encampment (best-of Castle and Coastal Reef) | ||
# ford snowy forest (Frozen, Forest, Flat, Shallow Water) | ||
# Keep | ||
# | ||
# Note: in 1.14 (and 1.15 at the time of writing), ford snowy forest's movement is | ||
# the worst of all four types, not the worst of (Frozen, Forest, Ford). | ||
# | ||
# 1, 1, 2, 2, 3, 2, 2, 3, 1, 1, 1, 3, 1 MP for an Elvish Archer | ||
# 1, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 3, 1 MP for an Orcish Grunt | ||
|
||
# Bob is always an orc, his movement is checked in every test run to check that | ||
# any effect in ALICE_MODIFICATION hasn't affected his movement costs. | ||
#define ORC_COSTS | ||
1,2,2,1,2,2,2,2,1,1,1,3,1 | ||
#enddef | ||
|
||
#define MOVETYPE_MOVE_SCEN ID ALICE_TYPE ALICE_MOVE_COSTS BOB_MOVE_COSTS ALICE_MODIFICATION | ||
[test] | ||
name = "Unit Test {ID}" | ||
map_data = "{test/maps/test_movetype.map}" | ||
turns = 1 | ||
id = {ID} | ||
random_start_time = no | ||
is_unit_test = yes | ||
|
||
{DEFAULT_SCHEDULE} | ||
|
||
[side] | ||
side=1 | ||
controller=human | ||
name = "Alice" | ||
type = {ALICE_TYPE} | ||
id=alice | ||
fog=no | ||
shroud=no | ||
share_view=no | ||
[/side] | ||
[side] | ||
side=2 | ||
controller=human | ||
name = "Bob" | ||
type = Orcish Grunt | ||
id=bob | ||
fog=no | ||
shroud=no | ||
share_view=no | ||
[/side] | ||
|
||
[event] | ||
name = prestart | ||
[set_variables] | ||
name=travelers | ||
mode=replace | ||
[split] | ||
list="alice,bob" | ||
key=id | ||
separator="," | ||
[/split] | ||
[/set_variables] | ||
[set_variables] | ||
name=expected_movement_cost | ||
mode=replace | ||
[split] | ||
list={ALICE_MOVE_COSTS} | ||
key=alice | ||
separator="," | ||
[/split] | ||
[/set_variables] | ||
[set_variables] | ||
name=expected_movement_cost | ||
mode=merge | ||
[split] | ||
list={BOB_MOVE_COSTS} | ||
key=bob | ||
separator="," | ||
[/split] | ||
[/set_variables] | ||
{ASSERT {VARIABLE_CONDITIONAL expected_movement_cost.length equals 13}} | ||
[/event] | ||
|
||
[event] | ||
name = side 1 turn 1 | ||
|
||
# This test uses [find_path] to get the movement costs of mixed terrains, | ||
# but if a path needs multiple turns then [find_path] will include the | ||
# cost of movement points that were left unused at the end of all turns | ||
# except the last. To avoid that, give the units enough MP. | ||
[modify_unit] | ||
[filter] | ||
[/filter] | ||
moves="$({UNREACHABLE} - 1)" | ||
max_moves="$({UNREACHABLE} - 1)" | ||
[/modify_unit] | ||
|
||
{ALICE_MODIFICATION} | ||
|
||
[foreach] | ||
array=travelers | ||
variable=traveler | ||
[do] | ||
[find_path] | ||
[traveler] | ||
id=$traveler.id | ||
[/traveler] | ||
[destination] | ||
location_id=destination | ||
[/destination] | ||
allow_multiple_turns=no | ||
variable=path | ||
[/find_path] | ||
# The path's steps include the starting hex, which is why there's | ||
# a +1 here and a +1 in the [for] loop. | ||
{ASSERT {VARIABLE_CONDITIONAL path.hexes not_equals 0}} | ||
{ASSERT {VARIABLE_CONDITIONAL path.step.length equals 14}} | ||
{VARIABLE expected_total 0} | ||
[for] | ||
array=expected_movement_cost | ||
[do] | ||
{VARIABLE i_plus_one "$($i + 1)"} | ||
[set_variable] | ||
name=expected_total | ||
add=$expected_movement_cost[$i].$traveler.id | ||
[/set_variable] | ||
{ASSERT {VARIABLE_CONDITIONAL path.step[$i_plus_one].movement_cost equals $expected_total}} | ||
[/do] | ||
[/for] | ||
[/do] | ||
[/foreach] | ||
|
||
{SUCCEED} | ||
[/event] | ||
[/test] | ||
#enddef | ||
|
||
# This test works by setting Alice's vision points, resetting the fog and then seeing how many hexes are visible. | ||
# The parameter ALICE_VISION_COSTS contains the values of each hex in the path from Alice to the destination, | ||
# so the same order as in the movement tests. Vision will also see the path towards Bob, for which this assumes that | ||
# the terrain adjacent to Bob's hex is the same as the terrain adjacent to Alice's. | ||
# | ||
# The vision cost of the location_id=destination hex will be ignored, as that hex becomes visible based on the cost | ||
# of the adjacent hex, however it's included in the macro argument for easier cut&paste from the MOVETYPE_MOVE_SCEN | ||
# tests. | ||
#define MOVETYPE_VISION_SCEN ID ALICE_TYPE ALICE_VISION_COSTS ALICE_MODIFICATION | ||
[test] | ||
name = "Unit Test {ID}" | ||
map_data = "{test/maps/test_movetype.map}" | ||
turns = 1 | ||
id = {ID} | ||
random_start_time = no | ||
is_unit_test = yes | ||
|
||
{DEFAULT_SCHEDULE} | ||
|
||
[side] | ||
side=1 | ||
controller=human | ||
name = "Alice" | ||
type = {ALICE_TYPE} | ||
id=alice | ||
fog=yes | ||
shroud=no | ||
share_view=no | ||
[/side] | ||
[side] | ||
side=2 | ||
controller=human | ||
name = "Bob" | ||
type = Orcish Grunt | ||
id=bob | ||
fog=yes | ||
shroud=no | ||
share_view=no | ||
[/side] | ||
|
||
[event] | ||
name = prestart | ||
[set_variables] | ||
name=expected_vision_costs | ||
mode=replace | ||
[split] | ||
list={ALICE_VISION_COSTS} | ||
key=alice | ||
separator="," | ||
[/split] | ||
[/set_variables] | ||
{ASSERT {VARIABLE_CONDITIONAL expected_vision_costs.length equals 13}} | ||
|
||
# This could be counted with a location filter, but other assumptions about the | ||
# map already need to be hardcoded in the test. | ||
{VARIABLE walkable_hexes_on_map 10} | ||
[/event] | ||
|
||
[event] | ||
name = side 1 turn 1 | ||
|
||
{ALICE_MODIFICATION} | ||
|
||
{VARIABLE vision_points 0} | ||
{VARIABLE expected_visible_count 0} | ||
[while] | ||
{VARIABLE_CONDITIONAL expected_visible_count less_than $walkable_hexes_on_map} | ||
{VARIABLE_CONDITIONAL ended boolean_equals no} # this is set by ASSERT | ||
[do] | ||
[modify_unit] | ||
[filter] | ||
id=alice | ||
[/filter] | ||
vision=$vision_points | ||
[/modify_unit] | ||
[reset_fog] | ||
[filter_side] | ||
side=1 | ||
[/filter_side] | ||
reset_view=true | ||
[/reset_fog] | ||
[redraw] | ||
side=1 | ||
clear_shroud=true | ||
[/redraw] | ||
|
||
# cumulative sum of the expected_vision_costs | ||
{VARIABLE expected_total 0} | ||
# We can always see the hex Alice is standing on and those adjacent to it, | ||
# for this test we ignore impassible hexes | ||
{VARIABLE expected_visible_count 2} | ||
# How many of the hexes towards the destination can we see? | ||
[for] | ||
array=expected_vision_costs | ||
[do] | ||
[set_variable] | ||
name=expected_total | ||
add=$expected_vision_costs[$i].alice | ||
[/set_variable] | ||
[if] | ||
{VARIABLE_CONDITIONAL vision_points greater_than_equal_to $expected_total} | ||
[then] | ||
[set_variable] | ||
name=expected_visible_count | ||
add=1 | ||
[/set_variable] | ||
[/then] | ||
[/if] | ||
[/do] | ||
[/for] | ||
# Add hexes towards Bob | ||
[if] | ||
{VARIABLE_CONDITIONAL vision_points greater_than_equal_to | ||
"$($expected_vision_costs[0].alice + $expected_vision_costs[1].alice)"} | ||
[then] | ||
[set_variable] | ||
name=expected_visible_count | ||
add=1 | ||
[/set_variable] | ||
[/then] | ||
[/if] | ||
[if] | ||
# Assume that the terrain adjacent to Bob's hex is the same as the terrain adjacent to Alice's. | ||
{VARIABLE_CONDITIONAL vision_points greater_than_equal_to | ||
"$(2 * $expected_vision_costs[0].alice + $expected_vision_costs[1].alice)"} | ||
[then] | ||
[set_variable] | ||
name=expected_visible_count | ||
add=1 | ||
[/set_variable] | ||
[/then] | ||
[/if] | ||
|
||
[store_locations] | ||
terrain=!,X* | ||
[filter_vision] | ||
side=1 | ||
visible=yes | ||
respect_fog=yes | ||
[/filter_vision] | ||
variable=visible_hexes | ||
[/store_locations] | ||
{ASSERT {VARIABLE_CONDITIONAL visible_hexes.length equals $expected_visible_count}} | ||
|
||
[set_variable] | ||
name=vision_points | ||
add=1 | ||
[/set_variable] | ||
[/do] | ||
[/while] | ||
|
||
{SUCCEED} | ||
[/event] | ||
[/test] | ||
#enddef | ||
|
||
#define SET_MOVE_COSTS COSTS | ||
[modify_unit] | ||
[filter] | ||
id=alice | ||
[/filter] | ||
[effect] | ||
apply_to=movement_costs | ||
replace=yes | ||
[movement_costs] | ||
{COSTS} | ||
[/movement_costs] | ||
[/effect] | ||
[/modify_unit] | ||
#enddef | ||
|
||
#define SET_VISION_COSTS COSTS | ||
[modify_unit] | ||
[filter] | ||
id=alice | ||
[/filter] | ||
[effect] | ||
apply_to=vision_costs | ||
replace=yes | ||
[vision_costs] | ||
{COSTS} | ||
[/vision_costs] | ||
[/effect] | ||
[/modify_unit] | ||
#enddef | ||
|
||
{MOVETYPE_MOVE_SCEN test_elf_movement (Elvish Archer) (1,1,2,2,3,2,2,3,1,1,1,3,1) {ORC_COSTS} ()} | ||
{MOVETYPE_MOVE_SCEN test_orc_movement (Orcish Grunt) {ORC_COSTS} {ORC_COSTS} ()} | ||
{MOVETYPE_MOVE_SCEN test_elf_fast_cave_movement (Elvish Archer) (1,1,2,2,2,2,2,2,1,1,1,3,1) {ORC_COSTS} {SET_MOVE_COSTS cave=1}} | ||
{MOVETYPE_MOVE_SCEN test_elf_fast_hills_movement (Elvish Archer) (1,1,1,1,3,2,2,3,1,1,1,3,1) {ORC_COSTS} {SET_MOVE_COSTS hills=1}} | ||
{MOVETYPE_MOVE_SCEN test_elf_fast_cave_and_hills_movement (Elvish Archer) (1,1,1,1,1,2,2,2,1,1,1,3,1) {ORC_COSTS} ({SET_MOVE_COSTS cave=1}{SET_MOVE_COSTS hills=1})} | ||
{MOVETYPE_MOVE_SCEN test_orc_fast_cave_movement (Orcish Grunt) (1,2,2,1,1,2,2,2,1,1,1,3,1) {ORC_COSTS} {SET_MOVE_COSTS cave=1}} | ||
{MOVETYPE_MOVE_SCEN test_orc_fast_forest_movement (Orcish Grunt) (1,1,1,1,2,2,2,2,1,1,1,3,1) {ORC_COSTS} {SET_MOVE_COSTS forest=1}} | ||
{MOVETYPE_MOVE_SCEN test_elf_slow_cave_movement (Elvish Archer) (1,1,2,2,4,2,2,4,1,1,1,3,1) {ORC_COSTS} {SET_MOVE_COSTS cave=4}} | ||
|
||
# changing the vision costs shouldn't affect the movement costs | ||
{MOVETYPE_MOVE_SCEN test_elf_longsighted_movement (Elvish Archer) (1,1,2,2,3,2,2,3,1,1,1,3,1) {ORC_COSTS} {SET_VISION_COSTS cave=1}} | ||
{MOVETYPE_MOVE_SCEN test_orc_longsighted_movement (Orcish Grunt) {ORC_COSTS} {ORC_COSTS} {SET_VISION_COSTS cave=1}} | ||
{MOVETYPE_MOVE_SCEN test_elf_longsighted_fast_cave_movement (Elvish Archer) (1,1,2,2,2,2,2,2,1,1,1,3,1) {ORC_COSTS} ({SET_VISION_COSTS hills=1}{SET_MOVE_COSTS cave=1})} | ||
{MOVETYPE_MOVE_SCEN test_elf_fast_cave_longsighted_movement (Elvish Archer) (1,1,2,2,2,2,2,2,1,1,1,3,1) {ORC_COSTS} ({SET_MOVE_COSTS cave=1}{SET_VISION_COSTS hills=1})} | ||
|
||
{MOVETYPE_VISION_SCEN test_elf_vision (Elvish Archer) (1,1,2,2,3,2,2,3,1,1,1,3,1) ()} | ||
# vision should fall back to movement, so these should match the movement numbers | ||
{MOVETYPE_VISION_SCEN test_elf_fast_cave_vision (Elvish Archer) (1,1,2,2,2,2,2,2,1,1,1,3,1) {SET_MOVE_COSTS cave=1}} | ||
{MOVETYPE_VISION_SCEN test_elf_fast_hills_vision (Elvish Archer) (1,1,1,1,3,2,2,3,1,1,1,3,1) {SET_MOVE_COSTS hills=1}} | ||
|
||
{MOVETYPE_VISION_SCEN test_elf_longsighted_cave_vision (Elvish Archer) (1,1,2,2,2,2,2,2,1,1,1,3,1) {SET_VISION_COSTS cave=1}} | ||
{MOVETYPE_VISION_SCEN test_elf_longsighted_cave_and_hills_vision (Elvish Archer) (1,1,1,1,1,2,2,2,1,1,1,3,1) ({SET_VISION_COSTS cave=1}{SET_VISION_COSTS hills=1})} | ||
{MOVETYPE_VISION_SCEN test_elf_longsighted_cave_slow_cave_vision (Elvish Archer) (1,1,2,2,2,2,2,2,1,1,1,3,1) ({SET_VISION_COSTS cave=1}{SET_MOVE_COSTS cave=4})} | ||
|
||
#undef SET_VISION_COSTS | ||
#undef SET_MOVE_COSTS | ||
#undef MOVETYPE_VISION_SCEN | ||
#undef MOVETYPE_MOVE_SCEN | ||
#undef ORC_COSTS |
Oops, something went wrong.