Skip to content

Commit

Permalink
tests: Move stamina/burdening to player_helpers
Browse files Browse the repository at this point in the history
Also test how many turns you can run with cardio mutations
  • Loading branch information
wapcaplet committed Dec 20, 2021
1 parent 8c3d3dc commit f2d32ba
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 65 deletions.
30 changes: 30 additions & 0 deletions tests/cardio_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
// - Good health vs. poor health
// - Running N tiles before getting winded

static const efftype_id effect_winded( "winded" );

static const move_mode_id move_mode_crouch( "crouch" );
static const move_mode_id move_mode_run( "run" );
static const move_mode_id move_mode_walk( "walk" );

static const skill_id skill_swimming( "swimming" );

// Base BMR for default character
Expand Down Expand Up @@ -75,6 +81,7 @@ TEST_CASE( "traits affecting cardio fitness level", "[cardio][fitness][traits]"
GIVEN( "Languorous (BADCARDIO) trait" ) {
set_single_trait( they, "BADCARDIO" );
REQUIRE( they.base_bmr() == base_bmr );

THEN( "cardio is reduced" ) {
const int expect_cardio = 0.75 * base_bmr;
CHECK( they.get_cardiofit() == Approx( expect_cardio ).margin( 2 ) );
Expand All @@ -83,22 +90,34 @@ TEST_CASE( "traits affecting cardio fitness level", "[cardio][fitness][traits]"
// Original stamina_max with mutation multiplier
//CHECK( they.get_stamina_max() == 6535 ); // 8714 * 0.75
}
THEN( "they can run for 35 turns" ) {
const int burn_per_turn = stamina_burn_rate( they, move_mode_run );
CHECK( burn_per_turn > 0 );
CHECK( they.get_stamina_max() / burn_per_turn == Approx( 35 ) );
}
}

// No cardio mutations - default avatar
GIVEN( "no cardio mutations or traits" ) {
clear_avatar();
REQUIRE( they.base_bmr() == base_bmr );

THEN( "cardio is normal" ) {
CHECK( they.get_cardiofit() == base_bmr );
CHECK( they.get_stamina_max() == base_stamina );
}
THEN( "they can run for 41 turns" ) {
const int burn_per_turn = stamina_burn_rate( they, move_mode_run );
CHECK( burn_per_turn > 0 );
CHECK( they.get_stamina_max() / burn_per_turn == Approx( 41 ) );
}
}

// cardio_multiplier = 1.25
GIVEN( "Indefatigable (GOODCARDIO) trait" ) {
set_single_trait( they, "GOODCARDIO" );
REQUIRE( they.base_bmr() == base_bmr );

THEN( "cardio is increased" ) {
const int expect_cardio = 1.25 * base_bmr;
CHECK( they.get_cardiofit() == Approx( expect_cardio ).margin( 2 ) );
Expand All @@ -107,12 +126,18 @@ TEST_CASE( "traits affecting cardio fitness level", "[cardio][fitness][traits]"
// Original stamina_max with mutation multiplier
//CHECK( they.get_stamina_max() == 10892 ); // 8714 * 1.25
}
THEN( "they can run for 47 turns" ) {
const int burn_per_turn = stamina_burn_rate( they, move_mode_run );
CHECK( burn_per_turn > 0 );
CHECK( they.get_stamina_max() / burn_per_turn == Approx( 47 ) );
}
}

// cardio_multiplier = 1.4
GIVEN( "Hyperactive (GOODCARDIO2) trait" ) {
set_single_trait( they, "GOODCARDIO2" );
REQUIRE( they.base_bmr() == base_bmr );

THEN( "cardio is increased more" ) {
const int expect_cardio = 1.4 * base_bmr;
CHECK( they.get_cardiofit() == Approx( expect_cardio ).margin( 2 ) );
Expand All @@ -121,6 +146,11 @@ TEST_CASE( "traits affecting cardio fitness level", "[cardio][fitness][traits]"
// Original stamina_max with mutation multiplier
//CHECK( they.get_stamina_max() == 12199 ); // 8714 * 1.4
}
THEN( "they can run for 51 turns" ) {
const int burn_per_turn = stamina_burn_rate( they, move_mode_run );
CHECK( burn_per_turn > 0 );
CHECK( they.get_stamina_max() / burn_per_turn == Approx( 51 ) );
}
}
}

Expand Down
65 changes: 0 additions & 65 deletions tests/char_stamina_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,71 +72,6 @@ static float move_cost_mod( Character &dummy, const move_mode_id &move_mode,
return dummy.get_modifier( character_modifier_stamina_move_cost_mod );
}

// Return amount of stamina burned per turn by `burn_move_stamina` in the given movement mode.
static int actual_burn_rate( Character &dummy, const move_mode_id &move_mode )
{
// Ensure we can run if necessary (aaaa zombies!)
dummy.set_stamina( dummy.get_stamina_max() );
catch_breath( dummy );
REQUIRE( dummy.can_run() );

// Walk, run, or crouch
dummy.set_movement_mode( move_mode );
REQUIRE( dummy.movement_mode_is( move_mode ) );

// Measure stamina burned, and ensure it is nonzero
int before_stam = dummy.get_stamina();
dummy.burn_move_stamina( to_moves<int>( 1_turns ) );
int after_stam = dummy.get_stamina();
REQUIRE( before_stam > after_stam );

// How much stamina was actually burned?
return before_stam - after_stam;
}

// Burden the Character with a given proportion [0.0 .. inf) of their maximum weight capacity
static void burden_player( Character &dummy, float burden_proportion )
{
units::mass capacity = dummy.weight_capacity();
// volatile float variable here to workaround a suspected compiler optimization related
// issue causing MinGW cross compile test failure
volatile float before_rounding = capacity * burden_proportion / 1_gram;
int units = static_cast<int>( before_rounding );

// Add a pile of test platinum bits (1g/unit) to reach the desired weight capacity
if( burden_proportion > 0.0 ) {
item pile( "test_platinum_bit", calendar::turn, units );
dummy.i_add( pile );
}

// Ensure we are carrying the expected number of grams
REQUIRE( to_gram( dummy.weight_carried() ) == units );
}

// Return amount of stamina burned per turn by `burn_move_stamina` in the given movement mode,
// while carrying the given proportion [0.0, inf) of their maximum weight capacity.
static int burdened_burn_rate( Character &dummy, const move_mode_id &move_mode,
float burden_proportion = 0.0 )
{
clear_avatar();
burden_player( dummy, burden_proportion );
return actual_burn_rate( dummy, move_mode );
}

// Return the actual amount of stamina regenerated by `update_stamina` in the given number of turns
static float actual_regen_rate( Character &dummy, int turns )
{
// Start at 10% stamina, plenty of space for regen
dummy.set_stamina( dummy.get_stamina_max() / 10 );
REQUIRE( dummy.get_stamina() == dummy.get_stamina_max() / 10 );

int before_stam = dummy.get_stamina();
dummy.update_stamina( turns );
int after_stam = dummy.get_stamina();

return after_stam - before_stam;
}

// Test cases
// ----------

Expand Down
67 changes: 67 additions & 0 deletions tests/player_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

static const itype_id itype_debug_backpack( "debug_backpack" );

static const efftype_id effect_winded( "winded" );

static const move_mode_id move_mode_walk( "walk" );

int get_remaining_charges( const std::string &tool_id )
Expand Down Expand Up @@ -265,3 +267,68 @@ item tool_with_ammo( const std::string &tool, const int qty )
}
return tool_it;
}

// Return amount of stamina burned per turn by `burn_move_stamina` in the given movement mode.
int stamina_burn_rate( Character &dummy, const move_mode_id &move_mode )
{
// Ensure we can run if necessary (aaaa zombies!)
dummy.set_stamina( dummy.get_stamina_max() );
dummy.remove_effect( effect_winded );
REQUIRE( dummy.can_run() );

// Walk, run, or crouch
dummy.set_movement_mode( move_mode );
REQUIRE( dummy.movement_mode_is( move_mode ) );

// Measure stamina burned, and ensure it is nonzero
int before_stam = dummy.get_stamina();
dummy.burn_move_stamina( to_moves<int>( 1_turns ) );
int after_stam = dummy.get_stamina();
REQUIRE( before_stam > after_stam );

// How much stamina was actually burned?
return before_stam - after_stam;
}

// Burden the Character with a given proportion [0.0 .. inf) of their maximum weight capacity
void burden_player( Character &dummy, float burden_proportion )
{
units::mass capacity = dummy.weight_capacity();
// volatile float variable here to workaround a suspected compiler optimization related
// issue causing MinGW cross compile test failure
volatile float before_rounding = capacity * burden_proportion / 1_gram;
int units = static_cast<int>( before_rounding );

// Add a pile of test platinum bits (1g/unit) to reach the desired weight capacity
if( burden_proportion > 0.0 ) {
item pile( "test_platinum_bit", calendar::turn, units );
dummy.i_add( pile );
}

// Ensure we are carrying the expected number of grams
REQUIRE( to_gram( dummy.weight_carried() ) == units );
}

// Return amount of stamina burned per turn by `burn_move_stamina` in the given movement mode,
// while carrying the given proportion [0.0, inf) of their maximum weight capacity.
int burdened_burn_rate( Character &dummy, const move_mode_id &move_mode, float burden_proportion )
{
clear_avatar();
burden_player( dummy, burden_proportion );
return stamina_burn_rate( dummy, move_mode );
}

// Return the actual amount of stamina regenerated by `update_stamina` in the given number of turns
float actual_regen_rate( Character &dummy, int turns )
{
// Start at 10% stamina, plenty of space for regen
dummy.set_stamina( dummy.get_stamina_max() / 10 );
REQUIRE( dummy.get_stamina() == dummy.get_stamina_max() / 10 );

int before_stam = dummy.get_stamina();
dummy.update_stamina( turns );
int after_stam = dummy.get_stamina();

return after_stam - before_stam;
}

6 changes: 6 additions & 0 deletions tests/player_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,10 @@ void arm_shooter( npc &shooter, const std::string &gun_type,

void equip_shooter( npc &shooter, const std::vector<std::string> &apparel );

int stamina_burn_rate( Character &dummy, const move_mode_id &move_mode );
void burden_player( Character &dummy, float burden_proportion );
int burdened_burn_rate( Character &dummy, const move_mode_id &move_mode,
float burden_proportion = 0.0 );
float actual_regen_rate( Character &dummy, int turns );

#endif // CATA_TESTS_PLAYER_HELPERS_H

0 comments on commit f2d32ba

Please sign in to comment.