Backstab unit tests: check that backstab works in a free-for-all

The units on the outsides of a backstab don't have to be allied
to each other, they just have to be enemies of the victim. That's
hardcoded into the AI via attack.cpp's backstab_check() function,
hence a unit test to check that WEAPON_SPECIAL_BACKSTAB activates
in that situation.

Add a new map with 4 sides all on separate castles. This is a
variation of the generic 2p unit test map, extended in the south
with a horizontal reflection of existing map.

Add a MAP_FILE argument to COMMON_KEEP_A_B_C_D_UNIT_TEST,
because it's the same setup except for the map file.
This commit is contained in:
Steve Cotton 2024-01-24 20:49:41 +01:00 committed by Steve Cotton
parent 866d1a7a6e
commit 84b1a778ae
5 changed files with 56 additions and 5 deletions

View file

@ -18,7 +18,10 @@
#
# The unit on hex spawn_points[0] then attacks Bob, and the test asserts
# that Bob has the expected number of hit points remaining.
{GENERIC_UNIT_TEST {NAME} (
#
# The map has 4 sides, none of the allied to each other, with the leaders
# of the other sides far enough away to not interfere with the test.
{COMMON_KEEP_A_B_C_D_UNIT_TEST {NAME} (
[event]
# Using this event instead of "start" because units get healed after "start", which makes debugging more confusing
name=side 1 turn 1
@ -98,5 +101,5 @@
{SUCCEED}
[/event]
)}
) (MAP_FILE="data/test/maps/4p_separate_castles.map")}
#enddef

View file

@ -8,18 +8,23 @@
# Side 3 leader Charlie (Orcish Grunt)
# Side 4 leader Dave (Orcish Grunt)
#
# All four leaders are on a single keep, with Alice and Bob already in position to attack any of the other units. None of the sides are allied.
# None of the sides are allied.
#
# There is no free castle hex to recruit onto.
# On the default map (used unless overridden with the MAP_FILE argument:
# * All four leaders are on a single keep, with Alice and Bob already in position to attack any of the other units.
# * There is no free castle hex to recruit onto.
##
#define COMMON_KEEP_A_B_C_D_UNIT_TEST NAME CONTENT
#arg SIDE_LEADER
Orcish Grunt#endarg
#arg MAP_FILE
test/maps/4p_single_castle.map#endarg
[test]
name=_ "Unit Test " + {NAME}
map_file=test/maps/4p_single_castle.map
map_file={MAP_FILE}
turns=unlimited
id={NAME}
random_start_time=no

View file

@ -0,0 +1,15 @@
Gg, Gg, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg, Gg^Kov, Gg^Kov, Gg^Kov, Gg, Gg^Kov, Gg^Kov, Gg^Kov, Gg
Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov
Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov
Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, 1 Kha^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, 2 Kha^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov
Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Cha^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Cha^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov
Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov
Gg^Kov, Gg^Kov, Gg^Kov, Chs^Kov, Gg^Kov, Chs^Kov, Gg^Kov, Ch^Kov, Gg^Kov, Ch^Kov, Gg^Kov, Chs^Kov, Gg^Kov, Ch^Kov, Gg^Kov, Ch^Kov, Gg^Kov, Gg^Kov
Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg
Gg^Kov, Gg^Kov, Gg^Kov, left Chs^Kov, Gg^Kov, Chs^Kov, Gg^Kov, Ch^Kov, Gg^Kov, Ch^Kov, Gg^Kov, Chs^Kov, Gg^Kov, Ch^Kov, Gg^Kov, right Ch^Kov, Gg^Kov, Gg
Gg, Gg^Kov, Gg^Kov, Gg^Kov, Gg, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg, Gg^Kov, Gg, Gg^Kov, Gg^Kov, Gg^Kov, Gg, Gg
Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Cha^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Cha^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov
Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, 3 Kha^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, 4 Kha^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov
Gg, Gg, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg, Gg^Kov, Gg^Kov, Gg^Kov, Gg, Gg^Kov, Gg^Kov, Gg^Kov, Gg
Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov
Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov, Gg^Kov

View file

@ -70,3 +70,30 @@
side=2
[/modify_unit]
)}
#####
# API(s) being tested: WEAPON_SPECIAL_BACKSTAB
##
# Actions:
# Bob is made to have 0% defense and given 100 hp.
# A Rogue is spawned north, south of Bob.
# The south Rogue is an enemy of both Bob and of the attacker.
# The north Rogue attacks Bob.
##
# Expected end state:
# The damage shows that Bob was backstabbed.
# Bob gets hit all three times and ends with 100-(6 * 3 * 2) hp.
#####
{GENERIC_BACKSTAB_TEST "backstab_active_with_free_for_all" "n,s" yes (
# Although the core weapon special is implemented using WFL,
# the logic is also hardcoded into the via in attack.cpp's
# function backstab_check(). This test is a reminder to change
# the C++ if someone changes the WFL.
[modify_unit]
[filter]
x=$spawn_points[1].x
y=$spawn_points[1].y
[/filter]
side=3
[/modify_unit]
)}

View file

@ -346,6 +346,7 @@
0 feeding_on_dead
0 firststrike_and_laststrike
0 backstab_active_with_accomplice_behind_bob
0 backstab_active_with_free_for_all
0 backstab_inactive_with_triangular_formation
0 backstab_inactive_with_statue_behind_bob
0 backstab_inactive_with_bobs_ally_behind_bob