-
-
Notifications
You must be signed in to change notification settings - Fork 991
/
test_movetype.cfg
362 lines (332 loc) · 13.9 KB
/
test_movetype.cfg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
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