forked from wesnoth/wesnoth
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Unit tests for [drains], [poison] and [slow], with apply_to=opponent
Slightly different to PR wesnoth#6582, which was the 1.16 version of this. The five lines that were labelled `preserving known bug` are changed to test that it's been fixed. Here `apply_to=opponent` means that the weapon special gives the opponent the ability, the unit that should get poisoned or slowed is the unit that has the weapon special. There's a known bug in 1.16, that `apply_to=opponent` check the wrong unit to see it it's `unpoisonable`, `undrainable` etc. It also checks the wrong unit to see if it's already poisoned or slowed, so a battle between two units that both have reverse-poison results in at most one being poisoned. 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. There's no test for [petrify], as simulate_combat doesn't provide a stat for it. This tests only 3 of the 6 abilities whose behavior changed in 650f704. My thoughts on testing the others are: * [firststrike]'s test is in 650f704. * [drains], [poison] and [slow] are tested here. * [petrify] ends combat, it's also not exposed in simulate_combat's stats. * [plague] triggers after combat ends.
- Loading branch information
1 parent
6dc52f0
commit 566618c
Showing
6 changed files
with
385 additions
and
9 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
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,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 |
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,165 @@ | ||
#textdomain wesnoth-test | ||
|
||
##### | ||
# API(s) being tested: [drains] | ||
## | ||
# Actions: | ||
# This uses a "common keep" map, with Alice and Bob already in position to attack any of the other units. | ||
# In this test they're all Orcish Grunts, so the all have 9x2 melee attacks. | ||
# Set everyone to 20 hp, so that drains will show but no-one will die. | ||
# Give Alice drains. | ||
# Give Bob reflexive drains. | ||
# Give Dave the undrainable trait. | ||
# Simulate various combats and check the results. | ||
## | ||
# Expected end state: | ||
# Alice drains Bob and Charlie | ||
# Charlie drains when attacking Bob | ||
# Dave drains in the Bob v Dave fight | ||
##### | ||
[test] | ||
name = _ "Unit Test reflexive_drains" | ||
map_file=test/maps/4p_single_castle.map | ||
turns = unlimited | ||
id = reflexive_drains | ||
is_unit_test = yes | ||
|
||
{DAWN} | ||
|
||
[side] | ||
side=1 | ||
controller=human | ||
[leader] | ||
name = _ "Alice" | ||
type = Orcish Grunt | ||
id=alice | ||
[/leader] | ||
[/side] | ||
[side] | ||
side=2 | ||
controller=human | ||
[leader] | ||
name = _ "Bob" | ||
type = Orcish Grunt | ||
id=bob | ||
[/leader] | ||
[/side] | ||
[side] | ||
side=3 | ||
controller=human | ||
[leader] | ||
name = _ "Charlie" | ||
type = Orcish Grunt | ||
id=charlie | ||
[/leader] | ||
[/side] | ||
[side] | ||
side=4 | ||
controller=human | ||
[leader] | ||
name = _ "Dave" | ||
type = Orcish Grunt | ||
id=dave | ||
[/leader] | ||
[/side] | ||
|
||
[event] | ||
name=start | ||
|
||
[object] | ||
[filter] | ||
id=alice | ||
[/filter] | ||
[effect] | ||
apply_to=attack | ||
[set_specials] | ||
mode=append | ||
{WEAPON_SPECIAL_DRAIN} | ||
[/set_specials] | ||
[/effect] | ||
[/object] | ||
|
||
[object] | ||
[filter] | ||
id=bob | ||
[/filter] | ||
[effect] | ||
apply_to=attack | ||
[set_specials] | ||
mode=append | ||
[drains] | ||
id=drains | ||
name= _ "drains" | ||
description= _ "Reverse drains, gives the drain ability to the opponent." | ||
apply_to=opponent | ||
[/drains] | ||
[/set_specials] | ||
[/effect] | ||
[/object] | ||
|
||
[object] | ||
[filter] | ||
id=dave | ||
[/filter] | ||
[effect] | ||
apply_to=status | ||
add=undrainable | ||
[/effect] | ||
[/object] | ||
|
||
[lua] | ||
code=<< | ||
local alice = wesnoth.units.find({id="alice"})[1] | ||
local bob = wesnoth.units.find({id="bob"})[1] | ||
local charlie = wesnoth.units.find({id="charlie"})[1] | ||
local dave = wesnoth.units.find({id="dave"})[1] | ||
|
||
alice.hitpoints = 20 | ||
bob.hitpoints = 20 | ||
charlie.hitpoints = 20 | ||
dave.hitpoints = 20 | ||
|
||
-- Everybody's an orcish grunt, and they're all on 60% terrain. The chance of {0,1,2} strikes hitting is: | ||
local hit_distribution = {} | ||
hit_distribution[0] = 0.6 ^ 2 | ||
hit_distribution[1] = 0.4 * 0.6 + 0.6 * 0.4 | ||
hit_distribution[2] = 0.4 ^ 2 | ||
-- Strikes do 9 damage each, and therefore drain heals 4 hp. Starting with 20 hp, each combination of getting | ||
-- hit i times and healing j times leads to a unique amount of hp after the fight. | ||
local expected_no_drain = {} | ||
local expected_with_drain = {} | ||
for i, i_chance in pairs(hit_distribution) do | ||
expected_no_drain[20 - 9 * i] = i_chance | ||
for j, j_chance in pairs(hit_distribution) do | ||
expected_with_drain[20 - 9 * i + 4 * j] = i_chance * j_chance | ||
end | ||
end | ||
|
||
function check_results(stats, expectation, log_message) | ||
for i,i_chance in pairs(expectation) do | ||
unit_test.assert_approx_equal(stats[i], i_chance, 0.001, log_message .. " expectation for " .. i .. " hp") | ||
end | ||
end | ||
|
||
-- Alice has drain, Bob has reflexive drain, Dave is undrainable | ||
local att_stats, def_stats = wesnoth.simulate_combat(alice, bob) | ||
check_results(att_stats.hp_chance, expected_with_drain, "Alice v Bob att_stats") | ||
check_results(def_stats.hp_chance, expected_no_drain, "Alice v Bob def_stats") | ||
att_stats, def_stats = wesnoth.simulate_combat(alice, charlie) | ||
check_results(att_stats.hp_chance, expected_with_drain, "Alice v Charlie att_stats") | ||
check_results(def_stats.hp_chance, expected_no_drain, "Alice v Charlie def_stats") | ||
att_stats, def_stats = wesnoth.simulate_combat(alice, dave) | ||
check_results(att_stats.hp_chance, expected_no_drain, "Alice v Dave att_stats") | ||
check_results(def_stats.hp_chance, expected_no_drain, "Alice v Dave def_stats") | ||
att_stats, def_stats = wesnoth.simulate_combat(bob, charlie) | ||
check_results(att_stats.hp_chance, expected_no_drain, "Bob v Charlie att_stats") | ||
check_results(def_stats.hp_chance, expected_with_drain, "Bob v Charlie def_stats") | ||
att_stats, def_stats = wesnoth.simulate_combat(bob, dave) | ||
check_results(att_stats.hp_chance, expected_no_drain, "Bob v Dave att_stats") | ||
check_results(def_stats.hp_chance, expected_with_drain, "Bob v Dave def_stats") | ||
>> | ||
[/lua] | ||
|
||
{SUCCEED} | ||
[/event] | ||
[/test] |
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,77 @@ | ||
#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. | ||
# Making Bob unpoisonable does not affect Alice. | ||
# Making Bob poisoned before combat starts does 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") | ||
-- Test the "unpoisonable" status on Alice (this works correctly, even in 1.16.x) | ||
local immune_alice = alice:clone() | ||
immune_alice.status.unpoisonable = true | ||
att_stats, def_stats = wesnoth.simulate_combat(immune_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, "Immune Alice should be unpoisonable") | ||
-- Test the "unpoisonable" status on Bob | ||
local immune_bob = bob:clone() | ||
immune_bob.status.unpoisonable = true | ||
att_stats, def_stats = wesnoth.simulate_combat(alice, 1, immune_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 when attacking Immune Bob") | ||
-- Test that Bob already being poisoned before combat starts doesn't affect the stats | ||
local affected_bob = bob:clone() | ||
affected_bob.status.poisoned = true | ||
att_stats, def_stats = wesnoth.simulate_combat(alice, 1, affected_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 when attacking Affected Bob") | ||
>> | ||
[/lua] | ||
|
||
{SUCCEED} | ||
[/event] | ||
)} |
Oops, something went wrong.