Skip to content

Commit bf2de61

Browse files
author
mqrause
committed
tests for activity interruption
1 parent 4cbcd6e commit bf2de61

File tree

3 files changed

+245
-0
lines changed

3 files changed

+245
-0
lines changed

tests/monster_helpers.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include "monster_helpers.h"
2+
3+
#include "item.h"
4+
#include "monster.h"
5+
6+
void move_monster_turn( monster &mon )
7+
{
8+
const int moves = mon.get_speed();
9+
mon.mod_moves( moves );
10+
while( mon.get_moves() > 0 ) {
11+
mon.move();
12+
}
13+
}

tests/monster_helpers.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
#ifndef CATA_TESTS_MONSTER_HELPERS_H
3+
#define CATA_TESTS_MONSTER_HELPERS_H
4+
5+
class monster;
6+
7+
void move_monster_turn( monster &mon );
8+
9+
#endif // CATA_TESTS_MONSTER_HELPERS_H

tests/player_activities_test.cpp

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "catch/catch.hpp"
22
#include "map_helpers.h"
3+
#include "monster_helpers.h"
34
#include "player_helpers.h"
45
#include "activity_scheduling_helper.h"
56

@@ -8,12 +9,14 @@
89
#include "calendar.h"
910
#include "character.h"
1011
#include "flag.h"
12+
#include "game.h"
1113
#include "itype.h"
1214
#include "iuse_actor.h"
1315
#include "map.h"
1416
#include "monster.h"
1517
#include "point.h"
1618

19+
static const activity_id ACT_AIM( "ACT_AIM" );
1720
static const activity_id ACT_BOLTCUTTING( "ACT_BOLTCUTTING" );
1821
static const activity_id ACT_CRACKING( "ACT_CRACKING" );
1922
static const activity_id ACT_HACKSAW( "ACT_HACKSAW" );
@@ -27,6 +30,8 @@ static const bionic_id bio_ears( "bio_ears" );
2730
static const efftype_id effect_pet( "pet" );
2831
static const efftype_id effect_tied( "tied" );
2932

33+
static const field_type_str_id field_fd_smoke( "fd_smoke" );
34+
3035
static const furn_str_id furn_test_f_boltcut1( "test_f_boltcut1" );
3136
static const furn_str_id furn_test_f_boltcut2( "test_f_boltcut2" );
3237
static const furn_str_id furn_test_f_boltcut3( "test_f_boltcut3" );
@@ -38,8 +43,10 @@ static const furn_str_id furn_test_f_oxytorch2( "test_f_oxytorch2" );
3843
static const furn_str_id furn_test_f_oxytorch3( "test_f_oxytorch3" );
3944
static const furn_str_id furn_test_f_prying1( "test_f_prying1" );
4045

46+
static const itype_id itype_book_binder( "book_binder" );
4147
static const itype_id itype_glass_shard( "glass_shard" );
4248
static const itype_id itype_oxyacetylene( "oxyacetylene" );
49+
static const itype_id itype_tent_kit( "tent_kit" );
4350
static const itype_id itype_test_2x4( "test_2x4" );
4451
static const itype_id itype_test_battery_disposable( "test_battery_disposable" );
4552
static const itype_id itype_test_boltcutter( "test_boltcutter" );
@@ -54,11 +61,13 @@ static const itype_id itype_test_rag( "test_rag" );
5461
static const itype_id itype_test_rock( "test_rock" );
5562
static const itype_id itype_test_shears( "test_shears" );
5663
static const itype_id itype_test_shears_off( "test_shears_off" );
64+
static const itype_id itype_water_clean( "water_clean" );
5765

5866
static const json_character_flag json_flag_SUPER_HEARING( "SUPER_HEARING" );
5967

6068
static const mtype_id mon_test_non_shearable( "mon_test_non_shearable" );
6169
static const mtype_id mon_test_shearable( "mon_test_shearable" );
70+
static const mtype_id mon_zombie( "mon_zombie" );
6271

6372
static const proficiency_id proficiency_prof_safecracking( "prof_safecracking" );
6473

@@ -68,8 +77,11 @@ static const quality_id qual_SAW_M( "SAW_M" );
6877
static const quality_id qual_SHEAR( "SHEAR" );
6978
static const quality_id qual_WELD( "WELD" );
7079

80+
static const recipe_id recipe_water_clean( "water_clean" );
81+
7182
static const skill_id skill_traps( "traps" );
7283

84+
static const ter_str_id ter_t_wall( "t_wall" );
7385
static const ter_str_id ter_test_t_boltcut1( "test_t_boltcut1" );
7486
static const ter_str_id ter_test_t_boltcut2( "test_t_boltcut2" );
7587
static const ter_str_id ter_test_t_hacksaw1( "test_t_hacksaw1" );
@@ -1654,3 +1666,214 @@ TEST_CASE( "prying", "[activity][prying]" )
16541666
}
16551667
}
16561668
}
1669+
1670+
/**
1671+
* Helper method to create activity stubs that aren't meant to be processed.
1672+
* The activities here still need to be able to pass activity_actor::start and
1673+
* set activity::moves_left to a value greater than 0.
1674+
* Some require a more complex setup for this, which is why they're commented out for now.
1675+
* To enable them, the activity would need to be paired with a setup method to be called
1676+
* before activity::start_or_resume to spawn necessary terrain/items/vehicles/etc.
1677+
* Activity actors that use ui functionality in their start methods cannot work at all,
1678+
* only affects workout_activity_actor right now
1679+
*/
1680+
static std::vector<player_activity> get_test_activities( avatar &dummy, map &m )
1681+
{
1682+
tripoint p = dummy.pos();
1683+
tripoint north = p + tripoint_north;
1684+
map_cursor c( p );
1685+
item_location loc;
1686+
std::vector<item_location> locs;
1687+
//this currently only works because the bookbinder is used in the first activity
1688+
//after that it's removed from the map
1689+
item &binderit = m.add_item( dummy.pos(), item( itype_book_binder ) );
1690+
item_location bookbinder( c, &binderit );
1691+
1692+
std::vector<player_activity> res{
1693+
//player_activity( autodrive_activity_actor() ),
1694+
//player_activity( bikerack_racking_activity_actor() ),
1695+
//player_activity( boltcutting_activity_actor( north, item_location() ) ),
1696+
player_activity( bookbinder_copy_activity_actor( bookbinder, recipe_water_clean ) ),
1697+
player_activity( consume_activity_actor( item( itype_water_clean ) ) ),
1698+
//player_activity( craft_activity_actor() ),
1699+
player_activity( dig_activity_actor( 1, p, "", north, 0, "" ) ),
1700+
player_activity( dig_channel_activity_actor( 1, p, "", north, 0, "" ) ),
1701+
//player_activity( disable_activity_actor() ),
1702+
//player_activity( disassemble_activity_actor( 1 ) ),
1703+
player_activity( drop_activity_actor() ),
1704+
//player_activity( ebooksave_activity_actor( loc, loc ) ),
1705+
player_activity( firstaid_activity_actor( 1, std::string() ) ),
1706+
player_activity( forage_activity_actor( 1 ) ),
1707+
player_activity( gunmod_remove_activity_actor( 1, loc, 0 ) ),
1708+
player_activity( hacking_activity_actor() ),
1709+
//player_activity( hacksaw_activity_actor( p, loc ) ),
1710+
player_activity( haircut_activity_actor() ),
1711+
//player_activity( harvest_activity_actor( p ) ),
1712+
player_activity( hotwire_car_activity_actor( 1, p ) ),
1713+
//player_activity( insert_item_activity_actor() ),
1714+
player_activity( lockpick_activity_actor::use_item( 1, loc, p ) ),
1715+
//player_activity( longsalvage_activity_actor() ),
1716+
player_activity( meditate_activity_actor() ),
1717+
player_activity( migration_cancel_activity_actor() ),
1718+
player_activity( milk_activity_actor( 1, {p}, {std::string()} ) ),
1719+
player_activity( mop_activity_actor( 1 ) ),
1720+
//player_activity( move_furniture_activity_actor( p, false ) ),
1721+
player_activity( move_items_activity_actor( {}, {}, false, north ) ),
1722+
player_activity( open_gate_activity_actor( 1, p ) ),
1723+
//player_activity( oxytorch_activity_actor( p, loc ) ),
1724+
player_activity( pickup_activity_actor( {}, {}, cata::nullopt ) ),
1725+
player_activity( play_with_pet_activity_actor() ),
1726+
//player_activity( prying_activity_actor( p, loc ) ),
1727+
//player_activity( read_activity_actor() ),
1728+
player_activity( reload_activity_actor( 1, 0, locs ) ),
1729+
player_activity( safecracking_activity_actor( north ) ),
1730+
player_activity( shave_activity_actor() ),
1731+
//player_activity( shearing_activity_actor( north ) ),
1732+
player_activity( stash_activity_actor() ),
1733+
player_activity( tent_deconstruct_activity_actor( 1, 1, p, itype_tent_kit ) ),
1734+
//player_activity( tent_placement_activity_actor() ),
1735+
player_activity( try_sleep_activity_actor( time_duration::from_hours( 1 ) ) ),
1736+
player_activity( unload_activity_actor( 1, loc ) ),
1737+
player_activity( wear_activity_actor( {}, {} ) ),
1738+
player_activity( wield_activity_actor( loc, 1 ) )
1739+
//player_activity( workout_activity_actor( p ) )
1740+
};
1741+
1742+
return res;
1743+
}
1744+
1745+
static void cleanup( avatar &dummy )
1746+
{
1747+
clear_map();
1748+
1749+
REQUIRE( dummy.activity.get_distractions().empty() );
1750+
REQUIRE( !dummy.activity.is_distraction_ignored( distraction_type::hostile_spotted_near ) );
1751+
REQUIRE( !dummy.activity.is_distraction_ignored( distraction_type::dangerous_field ) );
1752+
}
1753+
1754+
static void update_cache( map &m )
1755+
{
1756+
// Why twice? See vision_test.cpp
1757+
m.update_visibility_cache( 0 );
1758+
m.invalidate_map_cache( 0 );
1759+
m.build_map_cache( 0 );
1760+
m.update_visibility_cache( 0 );
1761+
m.invalidate_map_cache( 0 );
1762+
m.build_map_cache( 0 );
1763+
}
1764+
1765+
TEST_CASE( "activity interruption by distractions", "[activity][interruption]" )
1766+
{
1767+
avatar &dummy = get_avatar();
1768+
clear_avatar();
1769+
clear_map();
1770+
map &m = get_map();
1771+
calendar::turn = daylight_time( calendar::turn ) + 2_hours;
1772+
1773+
for( player_activity &activity : get_test_activities( dummy, m ) ) {
1774+
CAPTURE( activity.id() );
1775+
dummy.activity = activity;
1776+
dummy.activity.start_or_resume( dummy, false );
1777+
1778+
//this must be larger than 0 for interruption to happen
1779+
REQUIRE( dummy.activity.moves_left > 0 );
1780+
//some activities are set to null during start if they don't get valid data
1781+
REQUIRE( dummy.activity.id() != ACT_NULL );
1782+
//aiming is excluded from this kind of interruption
1783+
REQUIRE( dummy.activity.id() != ACT_AIM );
1784+
1785+
tripoint zombie_pos_near = dummy.pos() + tripoint( 2, 0, 0 );
1786+
tripoint zombie_pos_far = dummy.pos() + tripoint( 10, 0, 0 );
1787+
1788+
//to make section names unique
1789+
std::string act = activity.id().str();
1790+
1791+
SECTION( act + " interruption by nearby enemy" ) {
1792+
cleanup( dummy );
1793+
1794+
spawn_test_monster( mon_zombie.str(), zombie_pos_near );
1795+
update_cache( m );
1796+
1797+
std::map<distraction_type, std::string> dists = dummy.activity.get_distractions();
1798+
1799+
CHECK( dists.size() == 1 );
1800+
CHECK( dists.find( distraction_type::hostile_spotted_near ) != dists.end() );
1801+
}
1802+
1803+
SECTION( act + " enemy too far away to interrupt" ) {
1804+
cleanup( dummy );
1805+
1806+
monster &zombie = spawn_test_monster( mon_zombie.str(), zombie_pos_far );
1807+
update_cache( m );
1808+
1809+
REQUIRE( dummy.sees( zombie ) );
1810+
1811+
std::map<distraction_type, std::string> dists = dummy.activity.get_distractions();
1812+
1813+
CHECK( dists.empty() );
1814+
1815+
THEN( "interruption by zombie moving towards dummy" ) {
1816+
zombie.set_dest( get_map().getglobal( dummy.pos() ) );
1817+
int turns = 0;
1818+
do {
1819+
move_monster_turn( zombie );
1820+
dists = dummy.activity.get_distractions();
1821+
turns++;
1822+
} while( turns < 10 && dists.empty() );
1823+
1824+
CHECK( dists.size() == 1 );
1825+
CHECK( dists.find( distraction_type::hostile_spotted_near ) != dists.end() );
1826+
}
1827+
}
1828+
1829+
SECTION( act + " enemy nearby, but no line of sight" ) {
1830+
cleanup( dummy );
1831+
1832+
m.ter_set( dummy.pos() + tripoint_east, ter_t_wall );
1833+
monster &zombie = spawn_test_monster( mon_zombie.str(), zombie_pos_near );
1834+
update_cache( m );
1835+
1836+
REQUIRE( !dummy.sees( zombie ) );
1837+
1838+
std::map<distraction_type, std::string> dists = dummy.activity.get_distractions();
1839+
1840+
CHECK( dists.empty() );
1841+
1842+
THEN( "interruption by zombie moving towards dummy" ) {
1843+
zombie.set_dest( get_map().getglobal( dummy.pos() ) );
1844+
int turns = 0;
1845+
do {
1846+
move_monster_turn( zombie );
1847+
dists = dummy.activity.get_distractions();
1848+
turns++;
1849+
} while( turns < 5 && dists.empty() );
1850+
1851+
CHECK( dists.size() == 1 );
1852+
CHECK( dists.find( distraction_type::hostile_spotted_near ) != dists.end() );
1853+
}
1854+
}
1855+
1856+
SECTION( act + " interruption by dangerous field" ) {
1857+
cleanup( dummy );
1858+
1859+
m.add_field( dummy.pos(), field_fd_smoke );
1860+
1861+
std::map<distraction_type, std::string> dists = dummy.activity.get_distractions();
1862+
1863+
CHECK( dists.size() == 1 );
1864+
CHECK( dists.find( distraction_type::dangerous_field ) != dists.end() );
1865+
}
1866+
1867+
SECTION( act + " interruption by multiple sources" ) {
1868+
cleanup( dummy );
1869+
1870+
spawn_test_monster( mon_zombie.str(), zombie_pos_near );
1871+
m.add_field( dummy.pos(), field_fd_smoke );
1872+
std::map<distraction_type, std::string> dists = dummy.activity.get_distractions();
1873+
1874+
CHECK( dists.size() == 2 );
1875+
CHECK( dists.find( distraction_type::hostile_spotted_near ) != dists.end() );
1876+
CHECK( dists.find( distraction_type::dangerous_field ) != dists.end() );
1877+
}
1878+
}
1879+
}

0 commit comments

Comments
 (0)