Add tests for recursive weapon filters

This commit is contained in:
newfrenchy83 2024-06-01 18:39:58 +02:00 committed by Steve Cotton
parent 743b146efc
commit f272d9022e
3 changed files with 272 additions and 96 deletions

View file

@ -294,20 +294,7 @@
[/event]
)}
#####
# API(s) being tested: [event][filter_attack],[event][filter_second_attack]
##
# Actions:
# Define events filtering based on weapon specials.
# Give Bob a poison special iff the opponent has a specific drain special.
# Give Alice a drain special iff the opponent has a specific poison special.
# Have side 1's unit attack side 2's unit.
# Have side 2's unit attack side 1's unit.
##
# Expected end state:
# Both events that should trigger for Bob do trigger.
#####
{GENERIC_UNIT_TEST event_test_filter_attack_opponent_weapon_condition (
#define SPECIAL_CONDITION FILTER
[event]
name=turn 1
# Make sure the attacks hit
@ -339,9 +326,183 @@
[abilities]
[drains]
id=ability_drain_blade
[filter_opponent]
[filter_weapon]
{FILTER}
[/filter_weapon]
[/filter_opponent]
[/drains]
[/abilities]
[/effect]
[filter]
id=alice
[/filter]
[/object]
[modify_unit]
[filter]
[/filter]
# Make sure they don't die during the attacks
[status]
invulnerable=yes
[/status]
[/modify_unit]
{VARIABLE triggers 0}
{VARIABLE triggers_on_attack 0}
{VARIABLE triggers_on_defense 0}
[do_command]
[move]
x=7,13
y=3,4
[/move]
[attack]
[source]
x,y=13,4
[/source]
[destination]
x,y=13,3
[/destination]
[/attack]
[/do_command]
[end_turn][/end_turn]
[/event]
[event]
name=side 2 turn
[do_command]
[attack]
[source]
x,y=13,3
[/source]
[destination]
x,y=13,4
[/destination]
[/attack]
[/do_command]
[end_turn][/end_turn]
[/event]
[event]
name=attack
first_time_only=no
[filter_attack]
special_id_active=ability_poison_blade
[/filter_attack]
{ASSERT ({VARIABLE_CONDITIONAL side_number equals 2})}
{VARIABLE_OP triggers_on_attack add 1}
[/event]
[event]
name=attack
first_time_only=no
[filter_second_attack]
special_id_active=ability_poison_blade
[/filter_second_attack]
{ASSERT ({VARIABLE_CONDITIONAL side_number equals 1})}
{VARIABLE_OP triggers_on_defense add 1}
[/event]
#enddef
#####
# API(s) being tested: [event][filter_attack],[event][filter_second_attack]
##
# Actions:
# Define events filtering based on weapon specials.
# Give Bob a poison special iff the opponent has a specific drain special.
# Give Alice that drain special iff the opponent has a blade attack.
# Have side 1's unit attack side 2's unit.
# Have side 2's unit attack side 1's unit.
##
# Expected end state:
# Both events that should trigger for Bob do trigger.
#####
{GENERIC_UNIT_TEST event_test_filter_attack_opponent_weapon_condition (
{SPECIAL_CONDITION (type=blade)}
[event]
name=turn 2
{ASSERT ({VARIABLE_CONDITIONAL triggers_on_attack equals 1})}
{ASSERT ({VARIABLE_CONDITIONAL triggers_on_defense equals 1})}
{SUCCEED}
[/event]
)}
#####
# API(s) being tested: [event][filter_attack],[event][filter_second_attack]
##
# Actions:
# Define events filtering based on absence of weapon specials.
# Give Bob a poison special iff the opponent has a specific drain special, and that special is active.
# Give Alice a drain special iff the opponent has a specific poison special, and that special is active.
# Have side 1's unit attack side 2's unit.
# Have side 2's unit attack side 1's unit.
##
# Expected end state:
# BROKE STRICT because testing the special_id_active conditions led to infinite recursion.
# The events don't trigger. Both specials depend on the other one being active, so the calculation would need infinate recursion; instead, the engine decides that both are inactive.
#####
{GENERIC_UNIT_TEST event_test_filter_attack_opponent_weapon_condition_no_triggered (
{SPECIAL_CONDITION (special_id_active=ability_poison_blade)}
[event]
name=turn 2
{ASSERT ({VARIABLE_CONDITIONAL triggers_on_attack equals 0})}
{ASSERT ({VARIABLE_CONDITIONAL triggers_on_defense equals 0})}
{SUCCEED}
[/event]
)}
#undef SPECIAL_CONDITION
#####
# API(s) being tested: [event][filter_attack],[event][filter_second_attack]
##
# Actions:
# Define specials filtering based on weapon specials.
# Give Bob a poison special iff own a same special active or a blade or pierce attack.
# Give Alice a drain special iff own a same special active or a blade or pierce attack.
# Have side 1's unit attack side 2's unit.
# Have side 2's unit attack side 1's unit.
##
# Expected end state:
# BROKE STRICT because testing the special_id_active conditions led to infinite recursion.
# Both events trigger for Bob because testing type=blade,pierce only requires a reasonable depth of recursion.
#####
{GENERIC_UNIT_TEST event_test_filter_attack_student_weapon_condition (
[event]
name=turn 1
# Make sure the attacks hit
{FORCE_CHANCE_TO_HIT (id=bob) (id=alice) 100 ()}
{FORCE_CHANCE_TO_HIT (id=alice) (id=bob) 100 ()}
[object]
silent=yes
[effect]
apply_to=new_ability
[abilities]
[poison]
id=ability_poison_blade
[filter_student]
[filter_weapon]
type=blade
special_id_active=ability_poison_blade
[or]
type=blade,pierce
[/or]
[/filter_weapon]
[/filter_student]
[/poison]
[/abilities]
[/effect]
[filter]
id=bob
[/filter]
[/object]
[object]
silent=yes
[effect]
apply_to=new_ability
[abilities]
[drains]
id=ability_drain_blade
[filter_student]
[filter_weapon]
special_id_active=ability_drain_blade
[or]
type=blade,pierce
[/or]
[/filter_weapon]
[/filter_student]
[/drains]
@ -360,6 +521,8 @@
[/status]
[/modify_unit]
{VARIABLE triggers 0}
{VARIABLE triggers_on_attack 0}
{VARIABLE triggers_on_defense 0}
[do_command]
[move]
x=7,13

View file

@ -196,12 +196,14 @@
# Move Alice next to Bob, and have Alice attack Bob.
##
# Expected end state:
# Alice attack with fire; and Bob use cold because Bob [damage] filter must check type=blade and not the replacement type, that who cause infinite recursion.
# Alice attack with fire; and Bob use cold because Bob [damage] filter must check type=blade and not the replacement type. That's partly because it could otherwise cause infinite recursion, and partly because having a set limit to the number of recursions would make it unpredicatable which specials are active.
#####
{GENERIC_UNIT_TEST "damage_type_with_filter_test" (
{DAMAGE_TYPE_TEST {FILTER_TYPE_BLADE}}
)}
#undef FILTER_TYPE_BLADE
#####
# API(s) being tested: [damage]alternative_type=
##
@ -216,16 +218,10 @@
# Expected end state:
# Alice attack with blade and Bob use cold.
#####
{GENERIC_UNIT_TEST "damage_secondary_type_test" (
{COMMON_KEEP_A_B_UNIT_TEST "damage_secondary_type_test" (
[event]
name=start
[modify_unit]
[filter]
[/filter]
max_hitpoints=100
hitpoints=100
attacks_left=1
[/modify_unit]
[object]
silent=yes
[effect]
@ -240,27 +236,19 @@
apply_to=attack
[set_specials]
mode=append
[attacks]
value=1
[/attacks]
[damage]
value=12
[/damage]
[damage_type]
alternative_type=pierce
[/damage_type]
[damage_type]
alternative_type=cold
[/damage_type]
[chance_to_hit]
value=100
[/chance_to_hit]
[/set_specials]
[/effect]
[filter]
id=bob
[/filter]
[/object]
[object]
silent=yes
[effect]
@ -276,18 +264,9 @@
apply_to=attack
[set_specials]
mode=append
[attacks]
value=1
[/attacks]
[damage]
value=12
[/damage]
[damage_type]
alternative_type=fire
[/damage_type]
[chance_to_hit]
value=100
[/chance_to_hit]
[/set_specials]
[/effect]
[filter]
@ -295,60 +274,91 @@
[/filter]
[/object]
[store_unit]
[filter]
id=alice
[/filter]
variable=a
kill=yes
[/store_unit]
[store_unit]
[filter]
id=bob
[/filter]
variable=b
[/store_unit]
[unstore_unit]
variable=a
find_vacant=yes
x,y=$b.x,$b.y
[/unstore_unit]
[store_unit]
[filter]
id=alice
[/filter]
variable=a
[/store_unit]
[do_command]
[attack]
weapon=0
defender_weapon=0
[source]
x,y=$a.x,$a.y
[/source]
[destination]
x,y=$b.x,$b.y
[/destination]
[/attack]
[/do_command]
[store_unit]
[filter]
id=alice
[/filter]
variable=a
[/store_unit]
[store_unit]
[filter]
id=bob
[/filter]
variable=b
[/store_unit]
#damage without modification are 12, if test fail hitpoints !=76
#if succed then damage by alice 24(bob more vulnerable to blade)
#if succed then damage by bob 24(alice vulnerable to cold, cold [damage] is used)
{ASSERT ({VARIABLE_CONDITIONAL a.hitpoints equals 76})}
{ASSERT ({VARIABLE_CONDITIONAL b.hitpoints equals 76})}
# damage without modification is 100
# expected damage by alice is 200 (bob is vulnerable to blade, so the alternative isn't used)
# expected damage by bob is 200 (alice is most vulnerable to cold, so that alternative is used)
{ATTACK_AND_VALIDATE 200}
{SUCCEED}
[/event]
)}
#####
# API(s) being tested: [filter_self][has_attack]type= in [damage_type]
##
# Actions:
# Give Alice an ability that replace all damage by arcane if Alice has a blade attack
# Define events that use filter_attack matching Alice's arcane type.
# Have Alice attack Bob during side 1's turn
# Have Bob attack Alice during side 2's turn
##
# Expected end state:
# BROKE STRICT due to infinite recursion.
# The test reaches turn 2 without crashing; this tests for a C++ crash due to infinite recursion in the filters.
#####
{COMMON_KEEP_A_B_UNIT_TEST event_test_filter_damage_type_recursion (
[event]
name=start
[object]
silent=yes
[effect]
apply_to=new_ability
[abilities]
[damage_type]
id=test_arcane_damage
replacement_type=arcane
[filter_student]
[has_attack]
type=blade
[/has_attack]
[/filter_student]
[/damage_type]
[/abilities]
[/effect]
[filter]
id=alice
[/filter]
[/object]
[modify_unit]
[filter]
[/filter]
# Make sure they don't die during the attacks
[status]
invulnerable=yes
[/status]
[/modify_unit]
{VARIABLE triggers 0}
[/event]
[event]
name=side 1 turn 1
[test_do_attack_by_id]
attacker=alice
defender=bob
[/test_do_attack_by_id]
[end_turn][/end_turn]
[/event]
[event]
name=side 2 turn
[test_do_attack_by_id]
attacker=bob
defender=alice
[/test_do_attack_by_id]
[end_turn][/end_turn]
[/event]
# Event when Alice attacks
[event]
name=attack
first_time_only=no
[filter_attack]
type=arcane
[/filter_attack]
{ASSERT ({VARIABLE_CONDITIONAL side_number equals 1})}
{ASSERT ({VARIABLE_CONDITIONAL triggers equals 0})}
{VARIABLE_OP triggers add 1}
[/event]
[event]
name=turn 2
{RETURN ({VARIABLE_CONDITIONAL triggers equals 1})}
[/event]
)}

View file

@ -166,6 +166,8 @@
0 event_test_filter_attack_specials
0 event_test_filter_attack_on_moveto
0 event_test_filter_attack_opponent_weapon_condition
0 event_test_filter_attack_opponent_weapon_condition_no_triggered
0 event_test_filter_attack_student_weapon_condition
0 event_test_filter_wfl
0 event_test_filter_wfl2
0 event_test_filter_lua_serializable
@ -375,6 +377,7 @@
0 damage_type_test
0 damage_type_with_filter_test
0 damage_secondary_type_test
0 event_test_filter_damage_type_recursion
0 negative_resistance_with_two_attack_types
0 positive_resistance_with_two_attack_types
0 taught_resistance_with_two_attack_types