Skip to content

Commit

Permalink
Unit tests for [poison]apply_to=opponent
Browse files Browse the repository at this point in the history
Here `apply_to=opponent` means that the weapon special gives the opponent the
poison ability, the unit that should get poisoned is the unit that has the
weapon special.

As 1.16 has already been released, to avoid OOS the test is checking that the
current behavior's known bug is preserved. For the 1.17 branch the two tests
labelled `preserving known bug` will be changed to test the reverse.

Most of the credit for this is Newfrenchy's, as he's already written a fix
and a WML based test. This commit uses a Lua test instead to test more
combinations of statuses.

This adds a `COMMON_KEEP_A_B_UNIT_TEST` macro, which is a counterpart to the
`GENERIC_UNIT_TEST` macro that starts the leaders next to each other, ready
to attack. The `A_B` is because I'm planning a multiple-side variant too.
  • Loading branch information
stevecotton committed Mar 26, 2022
1 parent 30d02cb commit 7eaf9ce
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 9 deletions.
70 changes: 61 additions & 9 deletions data/test/macros/wml_unit_test_macros.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@
[/if]
#enddef

##
# Starting state:
# Side 1 leader Alice (Elvish Archer)
# Side 2 leader Bob (Orcish Grunt)
#
# Both leaders are on keeps separated by a few hexes, close enough for either
# of them to move next to the other leader in a single turn for an attack.
#
# Both keeps have space to recruit a single unit.
##
#define GENERIC_UNIT_TEST NAME CONTENT
#arg SIDE1_CONTROLLER
human#endarg
Expand Down Expand Up @@ -104,6 +114,48 @@ Elvish Archer#endarg
[/test]
#enddef

##
# Starting state:
# Side 1 leader Alice (Elvish Archer)
# Side 2 leader Bob (Orcish Grunt)
#
# Both leaders are on a single keep, adjacent to each other.
# There is no free castle hex to recruit onto.
##
#define COMMON_KEEP_A_B_UNIT_TEST NAME CONTENT
[test]
name=_ "Unit Test " + {NAME}
map_file=test/maps/2p_single_castle.map
turns=unlimited
id={NAME}
random_start_time=no
is_unit_test=yes

{DAWN}

[side]
side=1
controller=human
name=_ "Alice"
type=Elvish Archer
id=alice
fog=no
team_name=West
[/side]
[side]
side=2
controller=human
name=_ "Bob"
type=Orcish Grunt
id=bob
fog=no
team_name=East
[/side]

{CONTENT}
[/test]
#enddef

#define FAIL
{RETURN ([false][/false])}
#enddef
Expand All @@ -113,13 +165,13 @@ Elvish Archer#endarg
#enddef

#define FAIL_IF_NOT FLAG NOT_EQUALS
[if]
[variable]
name={FLAG}
not_equals={NOT_EQUALS}
[/variable]
[then]
{FAIL}
[/then]
[/if]
[if]
[variable]
name={FLAG}
not_equals={NOT_EQUALS}
[/variable]
[then]
{FAIL}
[/then]
[/if]
#enddef
7 changes: 7 additions & 0 deletions data/test/maps/2p_single_castle.map
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, 1 Ke, 2 Ke, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
79 changes: 79 additions & 0 deletions data/test/scenarios/reflexive_poison.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#textdomain wesnoth-test

#####
# API(s) being tested: [poison]apply_to=opponent
##
# Actions:
# This uses a "common keep" map, so Alice and Bob are already in position to attack.
# Give Alice a weapon that does reverse-poison (Alice gets poisoned if Bob hits her).
# Simulate various combats using melee weapons.
##
# Expected end state:
# Normal combat can poison Alice.
# Making Alice unpoisonable works.
# [known bug in 1.16] Making Bob unpoisonable should not affect Alice.
# [known bug in 1.16] Making Bob poisoned before combat starts should not affect Alice.
#####
{COMMON_KEEP_A_B_UNIT_TEST reflexive_poison (
[event]
name=start

[object]
[filter]
id=alice
[/filter]
[effect]
apply_to=attack
[set_specials]
mode=append
[poison]
id="reflexive_poison"
name=_ "reflexive_poison"
description=_ "When Alice attacks, her opponent’s weapons get the <i>poison</i> special."
apply_to=opponent
[/poison]
[/set_specials]
[/effect]
[/object]

[lua]
code=<<
local alice = wesnoth.units.find({id="alice"})[1]
local bob = wesnoth.units.find({id="bob"})[1]

-- Alice attacks with her sword, so Bob can counterattack. They're both on keeps, so 60% defense, and Bob gets 2 swings.
local expected_chance = 1.0 - 0.6 ^ 2
-- Test that the weapon special works, before adding any complications about status conditions
local att_stats, def_stats = wesnoth.simulate_combat(alice, 1, bob)
unit_test.assert_approx_equal(att_stats.untouched, 1.0 - expected_chance, 0.01, "Test setup failed - Alice should be at risk of getting hit")
unit_test.assert_approx_equal(att_stats.poisoned, expected_chance, 0.01, "Alice should be at risk of poisoning")
local unpoisonable_alice = alice:clone()
unpoisonable_alice.status.unpoisonable = true
local unpoisonable_bob = bob:clone()
unpoisonable_bob.status.unpoisonable = true
-- Test the "unpoisonable" status on Alice (this works correctly, even in 1.16.x)
att_stats, def_stats = wesnoth.simulate_combat(unpoisonable_alice, 1, bob)
unit_test.assert_approx_equal(att_stats.untouched, 1.0 - expected_chance, 0.01, "Test setup failed - Alice should be at risk of getting hit")
unit_test.assert_approx_equal(att_stats.poisoned, 0.0, 0.01, "Unpoisonable Alice should be unpoisonable")
-- Test the "unpoisonable" status on Bob (known bug in 1.16.x: Bob's unpoisonable status disables the poison special, even though it should affect Alice)
att_stats, def_stats = wesnoth.simulate_combat(alice, 1, unpoisonable_bob)
unit_test.assert_approx_equal(att_stats.untouched, 1.0 - expected_chance, 0.01, "Test setup failed - Alice should be at risk of getting hit")
unit_test.assert_approx_equal(att_stats.poisoned, 0.0, 0.01, "[preserving known bug] Alice should be at risk of poisoning when attacking Unpoisonable Bob")

local poisoned_bob = bob:clone()
poisoned_bob.status.poisoned = true

-- Test that Bob being poisoned doesn't affect the stats (known bug in 1.16.x: it does)
att_stats, def_stats = wesnoth.simulate_combat(alice, 1, unpoisonable_bob)
unit_test.assert_approx_equal(att_stats.untouched, 1.0 - expected_chance, 0.01, "Test setup failed - Alice should be at risk of getting hit")
unit_test.assert_approx_equal(att_stats.poisoned, 0.0, 0.01, "[preserving known bug] Alice should be at risk of poisoning when attacking Poisoned Bob")
>>
[/lua]
{SUCCEED}
[/event]
)}
1 change: 1 addition & 0 deletions wml_test_schedule
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@
0 backstab_without_enemy_behind
0 backstab_with_statue_behind
0 backstab_with_ally_behind
0 reflexive_poison
0 swarm_disables_upgrades
0 swarm_disables_upgrades_with_abilities
0 swarm_disables_upgrades_with_abilities_fail
Expand Down

0 comments on commit 7eaf9ce

Please sign in to comment.