From b290f8808248eb6cff8b7713022938c6ef941a7b Mon Sep 17 00:00:00 2001 From: actual-nh Date: Mon, 18 Jan 2021 21:50:25 -0500 Subject: [PATCH 01/13] Give more weary info; calories a bit less Give more detailed information on weariness (tracker and intake), to try to figure out why keeps going up and down during tests. Since the "healthy" stored calories are at bmi 25, put calories to healthy minus debug_nutrition, to prevent going over. (cherry picked from commit b8975403e16ff1a5ff0fa0f3ccf1f98fe03a7a1f) --- src/character.cpp | 10 ++++++++++ src/character.h | 2 ++ tests/activity_scheduling_helper.cpp | 14 ++++++++++---- tests/activity_scheduling_helper.h | 4 +++- tests/player_helpers.cpp | 5 +++-- 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 8c7976a2eaab0..a096741d93db7 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -5069,6 +5069,16 @@ std::string Character::debug_weary_info() const get_healthy_kcal(), fatigue, morale, weight, bmi ); } +int Character::weary_tracker() const +{ + return weary.tracker; +} + +int Character::weary_intake() const +{ + return weary.intake; +} + void weariness_tracker::clear() { tracker = 0; diff --git a/src/character.h b/src/character.h index 6cc305274e49a..19768aa3f6cd6 100644 --- a/src/character.h +++ b/src/character.h @@ -2730,6 +2730,8 @@ class Character : public Creature, public visitable int weariness_level() const; int weary_threshold() const; int weariness() const; + int weary_tracker() const; + int weary_intake() const; float activity_level() const; float exertion_adjusted_move_multiplier( float level = -1.0f ) const; void try_reduce_weariness( float exertion ); diff --git a/tests/activity_scheduling_helper.cpp b/tests/activity_scheduling_helper.cpp index d3e962705476d..022bede41d79a 100644 --- a/tests/activity_scheduling_helper.cpp +++ b/tests/activity_scheduling_helper.cpp @@ -112,8 +112,10 @@ weariness_events do_activity( tasklist tasks ) if( new_weariness != weariness_lvl ) { int new_weary = guy.weariness(); int new_thresh = guy.weary_threshold(); + int new_tracker = guy.weary_tracker(); + int new_intake = guy.weary_intake(); activity_log.log( weariness_lvl, new_weariness, spent, - new_weary, new_thresh ); + new_weary, new_thresh, new_tracker, new_intake ); weariness_lvl = new_weariness; } } @@ -171,7 +173,8 @@ time_duration tasklist::duration() } void weariness_events::log( const int old_level, const int new_level, const time_duration &when, - const int new_weariness, const int new_threshold ) + const int new_weariness, const int new_threshold, + const int new_tracker, const int new_intake ) { weary_transition added; added.from = old_level; @@ -179,6 +182,8 @@ void weariness_events::log( const int old_level, const int new_level, const time added.minutes = to_minutes( when ); added.new_weariness = new_weariness; added.new_threshold = new_threshold; + added.new_tracker = new_tracker; + added.new_intake = new_intake; transitions.insert( transitions.end(), added ); } @@ -202,9 +207,10 @@ std::string weariness_events::summarize() const { std::string buffer; for( const weary_transition &change : transitions ) { - buffer += string_format( "Transition: Weariness lvl from %d to %d at %d min (W %d Th %d)\n", + buffer += string_format( "Transition: Weariness lvl from %d to %d at %d min (W %d Th %d Tr %d In %d)\n", change.from, change.to, change.minutes, - change.new_weariness, change.new_threshold ); + change.new_weariness, change.new_threshold, + change.new_tracker, change.new_intake ); } return buffer; } diff --git a/tests/activity_scheduling_helper.h b/tests/activity_scheduling_helper.h index 4739bb2c45084..c0a446f8b1c31 100644 --- a/tests/activity_scheduling_helper.h +++ b/tests/activity_scheduling_helper.h @@ -95,13 +95,15 @@ struct weariness_events { int to = 0; int new_weariness = 0; int new_threshold = 0; + int new_tracker = 0; + int new_intake = 0; }; std::vector transitions; public: void log( int old_level, int new_level, const time_duration &when, - int new_weariness, int new_threshold ); + int new_weariness, int new_threshold, int new_tracker, int new_intake ); // Return the first time a transition between `from` and `to` occurs, in minutes // if around = 0_seconds or equivalent, otherwise return the time closest to around diff --git a/tests/player_helpers.cpp b/tests/player_helpers.cpp index ac99e158ab684..b77d069472a84 100644 --- a/tests/player_helpers.cpp +++ b/tests/player_helpers.cpp @@ -73,8 +73,9 @@ void clear_character( player &dummy ) // This sets HP to max, clears addictions and morale, // and sets hunger, thirst, fatigue and such to zero dummy.environmental_revert_effect(); - // However, the above does not set stored kcal - dummy.set_stored_kcal( dummy.get_healthy_kcal() ); + // However, the above does not set stored kcal; + // 2170 is calories of debug_nutrition + dummy.set_stored_kcal( dummy.get_healthy_kcal() - 2170 ); dummy.empty_skills(); dummy.martial_arts_data->clear_styles(); From c4ab6b29424c3aa5c0ead14cd4db7d577dffab48 Mon Sep 17 00:00:00 2001 From: actual-nh Date: Tue, 19 Jan 2021 11:43:25 -0500 Subject: [PATCH 02/13] Revert calories; prevent summary linewrapping The caloric subtraction (minus calories for debug_nutrition) is causing errors in other tests, and it is also desirable to make sure it isn't doing anything to the weariness tests themselves (weary intake). With the new information (weary tracker and intake), the summarize transition output is linewrapping; trying to prevent. (cherry picked from commit e96776721bc6e2048d681686e649111a541ab1c4) --- tests/activity_scheduling_helper.cpp | 2 +- tests/player_helpers.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/activity_scheduling_helper.cpp b/tests/activity_scheduling_helper.cpp index 022bede41d79a..c8df152c0d681 100644 --- a/tests/activity_scheduling_helper.cpp +++ b/tests/activity_scheduling_helper.cpp @@ -207,7 +207,7 @@ std::string weariness_events::summarize() const { std::string buffer; for( const weary_transition &change : transitions ) { - buffer += string_format( "Transition: Weariness lvl from %d to %d at %d min (W %d Th %d Tr %d In %d)\n", + buffer += string_format( "Transition: Weary lvl %d to %d at %d min (W %d Th %d Tr %d In %d)\n", change.from, change.to, change.minutes, change.new_weariness, change.new_threshold, change.new_tracker, change.new_intake ); diff --git a/tests/player_helpers.cpp b/tests/player_helpers.cpp index b77d069472a84..ac99e158ab684 100644 --- a/tests/player_helpers.cpp +++ b/tests/player_helpers.cpp @@ -73,9 +73,8 @@ void clear_character( player &dummy ) // This sets HP to max, clears addictions and morale, // and sets hunger, thirst, fatigue and such to zero dummy.environmental_revert_effect(); - // However, the above does not set stored kcal; - // 2170 is calories of debug_nutrition - dummy.set_stored_kcal( dummy.get_healthy_kcal() - 2170 ); + // However, the above does not set stored kcal + dummy.set_stored_kcal( dummy.get_healthy_kcal() ); dummy.empty_skills(); dummy.martial_arts_data->clear_styles(); From bdd942b3b0f6e09c76bbfc38bcc2989fdbdc6370 Mon Sep 17 00:00:00 2001 From: actual-nh Date: Sat, 6 Feb 2021 12:15:46 -0500 Subject: [PATCH 03/13] Start testing for unrealistic weary fluctuations Start on adding tests for unrealistic fluctuations in weary level; see #46384 (and some cases in #46941) for example problems. The initial tests look for problems with the weary_recovery task of digging for 8 hours then waiting for 8 hours; weary level should not go down in the first 8 hours, and should not go up in the second 8 hours. --- tests/weary_test.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/weary_test.cpp b/tests/weary_test.cpp index be3596f6c1827..3e0edc1e53064 100644 --- a/tests/weary_test.cpp +++ b/tests/weary_test.cpp @@ -127,6 +127,11 @@ TEST_CASE( "weary_recovery", "[weary][activities]" ) REQUIRE( !info.empty() ); CHECK( info.transition_minutes( 4, 3, 520_minutes ) == Approx( 520 ).margin( 5 ) ); CHECK( info.transition_minutes( 3, 2, 670_minutes ) == Approx( 670 ).margin( 5 ) ); + CHECK( info.transition_minutes( 1, 0, 0_minutes ) > ( 8 * 60 ) ); // should be INT_MAX + CHECK( info.transition_minutes( 2, 1, 0_minutes ) > ( 8 * 60 ) ); + CHECK( info.transition_minutes( 1, 2, 16_hours ) <= ( 8 * 60 ) ); + CHECK( info.transition_minutes( 2, 3, 16_hours ) <= ( 8 * 60 ) ); + CHECK( info.transition_minutes( 3, 4, 16_hours ) <= ( 8 * 60 ) ); CHECK( guy.weariness_level() == 1 ); } From 49fc6871b32a8c313509701072b27eb06586ab2b Mon Sep 17 00:00:00 2001 From: actual-nh Date: Tue, 9 Feb 2021 22:02:20 -0500 Subject: [PATCH 04/13] Add further weariness fluctuation testing In some conditions, namely continuous exercise at the same level, a decrease in weariness level is unrealistic. Check for this. --- tests/activity_scheduling_helper.cpp | 22 ++++++++++++++++++++++ tests/activity_scheduling_helper.h | 3 +++ tests/weary_test.cpp | 4 ++++ 3 files changed, 29 insertions(+) diff --git a/tests/activity_scheduling_helper.cpp b/tests/activity_scheduling_helper.cpp index c8df152c0d681..371acb4139336 100644 --- a/tests/activity_scheduling_helper.cpp +++ b/tests/activity_scheduling_helper.cpp @@ -203,6 +203,28 @@ int weariness_events::transition_minutes( const int from, const int to, return ret.first; } +bool weariness_events::have_weary_increase() const +{ + for( const weary_transition &change : transitions ) { + if( change.from < change.to ) { + return true; + } + } + + return false; +} + +bool weariness_events::have_weary_decrease() const +{ + for( const weary_transition &change : transitions ) { + if( change.from > change.to ) { + return true; + } + } + + return false; +} + std::string weariness_events::summarize() const { std::string buffer; diff --git a/tests/activity_scheduling_helper.h b/tests/activity_scheduling_helper.h index c0a446f8b1c31..f1b79789ab8b6 100644 --- a/tests/activity_scheduling_helper.h +++ b/tests/activity_scheduling_helper.h @@ -109,6 +109,9 @@ struct weariness_events { // if around = 0_seconds or equivalent, otherwise return the time closest to around int transition_minutes( int from, int to, const time_duration &around ) const; + bool have_weary_increase() const; + bool have_weary_decrease() const; + std::string summarize() const; bool empty() const; diff --git a/tests/weary_test.cpp b/tests/weary_test.cpp index 3e0edc1e53064..a2c57146c3003 100644 --- a/tests/weary_test.cpp +++ b/tests/weary_test.cpp @@ -57,6 +57,7 @@ TEST_CASE( "weary_assorted_tasks", "[weary][activities]" ) INFO( guy.debug_weary_info() ); REQUIRE( !info.empty() ); CHECK( info.transition_minutes( 0, 1, 370_minutes ) == Approx( 370 ).margin( 5 ) ); + CHECK( !info.have_weary_decrease() ); CHECK( guy.weariness_level() == 1 ); } @@ -71,6 +72,7 @@ TEST_CASE( "weary_assorted_tasks", "[weary][activities]" ) CHECK( info.transition_minutes( 1, 2, 255_minutes ) == Approx( 255 ).margin( 5 ) ); CHECK( info.transition_minutes( 2, 3, 360_minutes ) == Approx( 360 ).margin( 5 ) ); CHECK( info.transition_minutes( 3, 4, 470_minutes ) == Approx( 470 ).margin( 5 ) ); + CHECK( !info.have_weary_decrease() ); CHECK( guy.weariness_level() == 4 ); INFO( "\nDigging Pits 12 hours:" ); @@ -83,6 +85,7 @@ TEST_CASE( "weary_assorted_tasks", "[weary][activities]" ) CHECK( info.transition_minutes( 2, 3, 355_minutes ) == Approx( 355 ).margin( 5 ) ); CHECK( info.transition_minutes( 3, 4, 465_minutes ) == Approx( 465 ).margin( 5 ) ); CHECK( info.transition_minutes( 4, 5, 595_minutes ) == Approx( 595 ).margin( 5 ) ); + CHECK( !info.have_weary_decrease() ); CHECK( guy.weariness_level() == 5 ); } } @@ -183,6 +186,7 @@ TEST_CASE( "weary_24h_tasks", "[weary][activities]" ) CHECK( info.transition_minutes( 5, 6, 730_minutes ) == Approx( 730 ).margin( 5 ) ); CHECK( info.transition_minutes( 6, 7, 835_minutes ) == Approx( 835 ).margin( 5 ) ); CHECK( info.transition_minutes( 7, 8, 915_minutes ) == Approx( 915 ).margin( 10 ) ); + CHECK( !info.have_weary_decrease() ); // TODO: You should collapse from this - currently we // just get really high levels of weariness CHECK( guy.weariness_level() > 8 ); From 7b82317ced8ad5e417b1928610fbf6fe52e13c79 Mon Sep 17 00:00:00 2001 From: actual-nh Date: Tue, 9 Feb 2021 22:58:58 -0500 Subject: [PATCH 05/13] Adjust weary test output for readability Heavy tasks, while a logical section, do have the problem of repeating the earlier task's information, making it harder to tell which task triggered the message. Also make debug_weary_info() more informative using additional clear_avatar(). --- tests/weary_test.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/weary_test.cpp b/tests/weary_test.cpp index a2c57146c3003..6e4909c9c8bc3 100644 --- a/tests/weary_test.cpp +++ b/tests/weary_test.cpp @@ -51,6 +51,7 @@ TEST_CASE( "weary_assorted_tasks", "[weary][activities]" ) SECTION( "Moderate tasks" ) { INFO( "\nPlanting 8 hours:" ); + clear_avatar(); INFO( guy.debug_weary_info() ); weariness_events info = do_activity( moderate_8h ); INFO( info.summarize() ); @@ -61,8 +62,8 @@ TEST_CASE( "weary_assorted_tasks", "[weary][activities]" ) CHECK( guy.weariness_level() == 1 ); } - SECTION( "Heavy tasks" ) { - INFO( "\nDigging Pits 8 hours:" ); + SECTION( "Heavy tasks - Digging Pits 8 hours:" ) { + clear_avatar(); INFO( guy.debug_weary_info() ); weariness_events info = do_activity( soldier_8h ); INFO( info.summarize() ); @@ -74,8 +75,11 @@ TEST_CASE( "weary_assorted_tasks", "[weary][activities]" ) CHECK( info.transition_minutes( 3, 4, 470_minutes ) == Approx( 470 ).margin( 5 ) ); CHECK( !info.have_weary_decrease() ); CHECK( guy.weariness_level() == 4 ); + } - INFO( "\nDigging Pits 12 hours:" ); + SECTION( "Heavy tasks - Digging Pits 12 hours:" ) { + clear_avatar(); + INFO( guy.debug_weary_info() ); info = do_activity( soldier_12h ); INFO( info.summarize() ); INFO( guy.debug_weary_info() ); @@ -140,6 +144,7 @@ TEST_CASE( "weary_recovery", "[weary][activities]" ) SECTION( "1 day vehicle work" ) { INFO( "\n3 meals, 10h vehicle work, 4h reading, 10h sleep, 16h waiting" ); + clear_avatar(); INFO( guy.debug_weary_info() ); weariness_events info = do_activity( mechanic_day ); INFO( info.summarize() ); @@ -173,6 +178,7 @@ TEST_CASE( "weary_24h_tasks", "[weary][activities]" ) } SECTION( "Digging 24 hours" ) { + clear_avatar(); INFO( guy.debug_weary_info() ); weariness_events info = do_activity( digging_24h ); INFO( info.summarize() ); From f37d2170f5455c34c1084909fb1a53eca393ecd5 Mon Sep 17 00:00:00 2001 From: actual-nh Date: Tue, 9 Feb 2021 23:09:23 -0500 Subject: [PATCH 06/13] Make earlier commit actually work. Forgot to copy over identifier declaration. --- tests/weary_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/weary_test.cpp b/tests/weary_test.cpp index 6e4909c9c8bc3..ed79ce903dace 100644 --- a/tests/weary_test.cpp +++ b/tests/weary_test.cpp @@ -80,7 +80,7 @@ TEST_CASE( "weary_assorted_tasks", "[weary][activities]" ) SECTION( "Heavy tasks - Digging Pits 12 hours:" ) { clear_avatar(); INFO( guy.debug_weary_info() ); - info = do_activity( soldier_12h ); + weariness_events info = do_activity( soldier_12h ); INFO( info.summarize() ); INFO( guy.debug_weary_info() ); REQUIRE( !info.empty() ); From db03ee58f3a6570a71ffca91d17eed42e7372ff8 Mon Sep 17 00:00:00 2001 From: actual-nh Date: Wed, 10 Feb 2021 21:03:24 -0500 Subject: [PATCH 07/13] Smooth out weary intake/tracker a bit Weary levels keep fluctuating unrealistically, probably because weary.intake (and weary.tracker?) are changing in large jumps at times. --- src/character.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index a096741d93db7..cf458bcf3d14a 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -5697,24 +5697,24 @@ void Character::try_reduce_weariness( const float exertion ) } const float recovery_mult = get_option( "WEARY_RECOVERY_MULT" ); + const int bmr = base_bmr(); - if( weary.low_activity_ticks >= 6 ) { + while( weary.low_activity_ticks >= 6 ) { int reduction = weary.tracker; - const int bmr = base_bmr(); // 1/20 of whichever's bigger if( bmr > reduction ) { reduction = bmr * recovery_mult; } else { reduction *= recovery_mult; } - weary.low_activity_ticks = 0; + weary.low_activity_ticks -= 6; weary.tracker -= reduction; } - if( weary.tick_counter >= 12 ) { - weary.intake *= 1 - recovery_mult; - weary.tick_counter = 0; + if( weary.tick_counter >= 6 ) { + weary.intake *= std::sqrt( 1 - recovery_mult ); + weary.tick_counter -= 6; } // Normalize values, make sure we stay above 0 From 028b0f0ca6a4242231731ee74ab124e5ce611606 Mon Sep 17 00:00:00 2001 From: actual-nh Date: Thu, 11 Feb 2021 11:22:02 -0500 Subject: [PATCH 08/13] Adjust for smoothing weary intake/tracker This adjusts expected test values to the (quite consistent) ones for the altered weary intake/tracker. It also does the weary.tracker adjustment in a less-perfectionistic (but more-functional) way. --- src/character.cpp | 6 +++--- tests/weary_test.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index cf458bcf3d14a..41730615a7b58 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -5690,17 +5690,17 @@ void Character::try_reduce_weariness( const float exertion ) weary.tick_counter++; if( exertion == NO_EXERCISE ) { weary.low_activity_ticks++; - // Recover twice as fast at rest + // Recover twice as fast if asleep if( in_sleep_state() ) { weary.low_activity_ticks++; } } const float recovery_mult = get_option( "WEARY_RECOVERY_MULT" ); - const int bmr = base_bmr(); - while( weary.low_activity_ticks >= 6 ) { + if( weary.low_activity_ticks >= 6 ) { int reduction = weary.tracker; + const int bmr = base_bmr(); // 1/20 of whichever's bigger if( bmr > reduction ) { reduction = bmr * recovery_mult; diff --git a/tests/weary_test.cpp b/tests/weary_test.cpp index ed79ce903dace..806f51a993ae7 100644 --- a/tests/weary_test.cpp +++ b/tests/weary_test.cpp @@ -62,7 +62,7 @@ TEST_CASE( "weary_assorted_tasks", "[weary][activities]" ) CHECK( guy.weariness_level() == 1 ); } - SECTION( "Heavy tasks - Digging Pits 8 hours:" ) { + SECTION( "Heavy tasks - Digging Pits 8 hours" ) { clear_avatar(); INFO( guy.debug_weary_info() ); weariness_events info = do_activity( soldier_8h ); @@ -77,7 +77,7 @@ TEST_CASE( "weary_assorted_tasks", "[weary][activities]" ) CHECK( guy.weariness_level() == 4 ); } - SECTION( "Heavy tasks - Digging Pits 12 hours:" ) { + SECTION( "Heavy tasks - Digging Pits 12 hours" ) { clear_avatar(); INFO( guy.debug_weary_info() ); weariness_events info = do_activity( soldier_12h ); @@ -133,7 +133,7 @@ TEST_CASE( "weary_recovery", "[weary][activities]" ) INFO( guy.debug_weary_info() ); REQUIRE( !info.empty() ); CHECK( info.transition_minutes( 4, 3, 520_minutes ) == Approx( 520 ).margin( 5 ) ); - CHECK( info.transition_minutes( 3, 2, 670_minutes ) == Approx( 670 ).margin( 5 ) ); + CHECK( info.transition_minutes( 3, 2, 640_minutes ) == Approx( 640 ).margin( 5 ) ); CHECK( info.transition_minutes( 1, 0, 0_minutes ) > ( 8 * 60 ) ); // should be INT_MAX CHECK( info.transition_minutes( 2, 1, 0_minutes ) > ( 8 * 60 ) ); CHECK( info.transition_minutes( 1, 2, 16_hours ) <= ( 8 * 60 ) ); @@ -189,8 +189,8 @@ TEST_CASE( "weary_24h_tasks", "[weary][activities]" ) CHECK( info.transition_minutes( 2, 3, 360_minutes ) == Approx( 360 ).margin( 5 ) ); CHECK( info.transition_minutes( 3, 4, 470_minutes ) == Approx( 470 ).margin( 5 ) ); CHECK( info.transition_minutes( 4, 5, 595_minutes ) == Approx( 595 ).margin( 5 ) ); - CHECK( info.transition_minutes( 5, 6, 730_minutes ) == Approx( 730 ).margin( 5 ) ); - CHECK( info.transition_minutes( 6, 7, 835_minutes ) == Approx( 835 ).margin( 5 ) ); + CHECK( info.transition_minutes( 5, 6, 740_minutes ) == Approx( 740 ).margin( 5 ) ); + CHECK( info.transition_minutes( 6, 7, 845_minutes ) == Approx( 845 ).margin( 5 ) ); CHECK( info.transition_minutes( 7, 8, 915_minutes ) == Approx( 915 ).margin( 10 ) ); CHECK( !info.have_weary_decrease() ); // TODO: You should collapse from this - currently we From 45b1139c5b1f942b390796268de61d8139316465 Mon Sep 17 00:00:00 2001 From: actual-nh Date: Thu, 11 Feb 2021 20:19:28 -0500 Subject: [PATCH 09/13] Temporarily allow expected failures on 2 tests. Two of the tests are doing a consistent failure due to fluctuations. Ultimately, these fluctuations need eliminating, but it would be nice to get some information on if anything else is going on. --- tests/weary_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/weary_test.cpp b/tests/weary_test.cpp index 806f51a993ae7..165b53e7fbb17 100644 --- a/tests/weary_test.cpp +++ b/tests/weary_test.cpp @@ -22,7 +22,7 @@ static const meal_schedule milk( itype_id( "milk" ) ); static const sleep_schedule sched_sleep{}; -TEST_CASE( "weary_assorted_tasks", "[weary][activities]" ) +TEST_CASE( "weary_assorted_tasks", "[weary][activities][!mayfail]" ) { const avatar &guy = get_avatar(); From ab4ba67cc56a3f2519851c81ba512fe0378a75e8 Mon Sep 17 00:00:00 2001 From: actual-nh Date: Wed, 17 Feb 2021 23:56:26 -0500 Subject: [PATCH 10/13] Smoothen weary tracker+intake reductions This is an extension of a previous modification to try to smooth out the weary.intake reduction (smaller changes but more frequent), and both increases that and does similar for weary.tracker. The weary.intake changes are leading up to - probably after 0.F - an exponential moving average being used instead, so that characters are not, essentially hypoglycemic. --- src/character.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 41730615a7b58..18d7c9972f24b 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -5690,7 +5690,7 @@ void Character::try_reduce_weariness( const float exertion ) weary.tick_counter++; if( exertion == NO_EXERCISE ) { weary.low_activity_ticks++; - // Recover twice as fast if asleep + // Recover twice as fast if asleep/similar if( in_sleep_state() ) { weary.low_activity_ticks++; } @@ -5698,23 +5698,24 @@ void Character::try_reduce_weariness( const float exertion ) const float recovery_mult = get_option( "WEARY_RECOVERY_MULT" ); - if( weary.low_activity_ticks >= 6 ) { + if( weary.low_activity_ticks >= 3 ) { int reduction = weary.tracker; const int bmr = base_bmr(); - // 1/20 of whichever's bigger + // 1/40 of whichever's bigger if( bmr > reduction ) { - reduction = bmr * recovery_mult; + reduction = std::floor( bmr * recovery_mult * 0.5f ); } else { - reduction *= recovery_mult; + reduction = std::ceil( reduction * recovery_mult * 0.5f ); } - weary.low_activity_ticks -= 6; + weary.low_activity_ticks -= 3; - weary.tracker -= reduction; + weary.tracker -= std::max( reduction, 1 ); } - if( weary.tick_counter >= 6 ) { - weary.intake *= std::sqrt( 1 - recovery_mult ); - weary.tick_counter -= 6; + // If happens to be no reduction, character is not (as) hypoglycemic + if( weary.tick_counter >= 3 ) { + weary.intake *= std::pow( 1 - recovery_mult, 0.25f ); + weary.tick_counter -= 3; } // Normalize values, make sure we stay above 0 From c01a6611f7c65cd787022a58393cf65e9de9f563 Mon Sep 17 00:00:00 2001 From: actual-nh Date: Thu, 18 Feb 2021 17:03:31 -0500 Subject: [PATCH 11/13] Check on weary ticks. This monitors, with weary level transitions, the low_activity_ticks and tick_counter, to see if this can help figure out why weary.tracker is increasing while resting. (cherry picked from commit 4c4b9cdba30ebcbe06236bdcb51a02d16234148a) --- src/character.cpp | 10 ++++++++++ src/character.h | 2 ++ tests/activity_scheduling_helper.cpp | 17 ++++++++++++----- tests/activity_scheduling_helper.h | 5 ++++- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 18d7c9972f24b..461fa8b40607e 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -5079,6 +5079,16 @@ int Character::weary_intake() const return weary.intake; } +int Character::weary_low_activity_ticks() const +{ + return weary.low_activity_ticks; +} + +int Character::weary_tick_counter() const +{ + return weary.tick_counter; +} + void weariness_tracker::clear() { tracker = 0; diff --git a/src/character.h b/src/character.h index 19768aa3f6cd6..9f0f1df91c38f 100644 --- a/src/character.h +++ b/src/character.h @@ -2732,6 +2732,8 @@ class Character : public Creature, public visitable int weariness() const; int weary_tracker() const; int weary_intake() const; + int weary_low_activity_ticks() const; + int weary_tick_counter() const; float activity_level() const; float exertion_adjusted_move_multiplier( float level = -1.0f ) const; void try_reduce_weariness( float exertion ); diff --git a/tests/activity_scheduling_helper.cpp b/tests/activity_scheduling_helper.cpp index 371acb4139336..94e989bc97b67 100644 --- a/tests/activity_scheduling_helper.cpp +++ b/tests/activity_scheduling_helper.cpp @@ -108,14 +108,17 @@ weariness_events do_activity( tasklist tasks ) int new_weariness = guy.weariness_level(); spent += task.interval; tasks.advance( task.interval ); - // If we're more weary than we were when we started, report it + // If we're more or less weary than we were when we started, report it if( new_weariness != weariness_lvl ) { int new_weary = guy.weariness(); int new_thresh = guy.weary_threshold(); int new_tracker = guy.weary_tracker(); int new_intake = guy.weary_intake(); + int new_low_activity_ticks = guy.weary_low_activity_ticks(); + int new_tick_counter = guy.weary_tick_counter(); activity_log.log( weariness_lvl, new_weariness, spent, - new_weary, new_thresh, new_tracker, new_intake ); + new_weary, new_thresh, new_tracker, new_intake, + new_low_activity_ticks, new_tick_counter ); weariness_lvl = new_weariness; } } @@ -174,7 +177,8 @@ time_duration tasklist::duration() void weariness_events::log( const int old_level, const int new_level, const time_duration &when, const int new_weariness, const int new_threshold, - const int new_tracker, const int new_intake ) + const int new_tracker, const int new_intake, + const int new_low_activity_ticks, const int new_tick_counter ) { weary_transition added; added.from = old_level; @@ -184,6 +188,8 @@ void weariness_events::log( const int old_level, const int new_level, const time added.new_threshold = new_threshold; added.new_tracker = new_tracker; added.new_intake = new_intake; + added.new_low_activity_ticks = new_low_activity_ticks; + added.new_tick_counter = new_tick_counter; transitions.insert( transitions.end(), added ); } @@ -229,10 +235,11 @@ std::string weariness_events::summarize() const { std::string buffer; for( const weary_transition &change : transitions ) { - buffer += string_format( "Transition: Weary lvl %d to %d at %d min (W %d Th %d Tr %d In %d)\n", + buffer += string_format( "Chng: Weary lv %d to %d at %d min (W %d Th %d Tr %d In %d Lt %d Tk %d)\n", change.from, change.to, change.minutes, change.new_weariness, change.new_threshold, - change.new_tracker, change.new_intake ); + change.new_tracker, change.new_intake, + change.new_low_activity_ticks, change.new_tick_counter ); } return buffer; } diff --git a/tests/activity_scheduling_helper.h b/tests/activity_scheduling_helper.h index f1b79789ab8b6..b32c0375677da 100644 --- a/tests/activity_scheduling_helper.h +++ b/tests/activity_scheduling_helper.h @@ -97,13 +97,16 @@ struct weariness_events { int new_threshold = 0; int new_tracker = 0; int new_intake = 0; + int new_low_activity_ticks = 0; + int new_tick_counter = 0; }; std::vector transitions; public: void log( int old_level, int new_level, const time_duration &when, - int new_weariness, int new_threshold, int new_tracker, int new_intake ); + int new_weariness, int new_threshold, int new_tracker, int new_intake, + int new_low_activity_ticks, int new_tick_counter ); // Return the first time a transition between `from` and `to` occurs, in minutes // if around = 0_seconds or equivalent, otherwise return the time closest to around From 5d9dcb270948adae0955433bb0b5df1eb41aa1fd Mon Sep 17 00:00:00 2001 From: actual-nh Date: Fri, 19 Feb 2021 22:41:09 -0500 Subject: [PATCH 12/13] Make weary.tracker reduction happen every time As far as I can tell, the cause of the weary.tracker going up during resting periods is that rest does still expend calories (bmr), and it happens every 5 minutes - while weary.tracker was only reduced every 30 (current) or 15 (this branch) minutes. This commit makes weary.tracker reduction occur every 5 minutes - every time try_reduce_weariness() is called. --- src/character.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 461fa8b40607e..71c9bdb4e3771 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -5708,16 +5708,16 @@ void Character::try_reduce_weariness( const float exertion ) const float recovery_mult = get_option( "WEARY_RECOVERY_MULT" ); - if( weary.low_activity_ticks >= 3 ) { + if( weary.low_activity_ticks > 0 ) { int reduction = weary.tracker; const int bmr = base_bmr(); - // 1/40 of whichever's bigger + // 1/120 of whichever's bigger if( bmr > reduction ) { - reduction = std::floor( bmr * recovery_mult * 0.5f ); + reduction = std::floor( bmr * recovery_mult * weary.low_activity_ticks / 6 ); } else { - reduction = std::ceil( reduction * recovery_mult * 0.5f ); + reduction = std::ceil( reduction * recovery_mult * weary.low_activity_ticks / 6 ); } - weary.low_activity_ticks -= 3; + weary.low_activity_ticks = 0; weary.tracker -= std::max( reduction, 1 ); } From c68507b004e0bce5669a3c59a0f5161ae157c828 Mon Sep 17 00:00:00 2001 From: actual-nh Date: Sat, 20 Feb 2021 12:33:30 -0500 Subject: [PATCH 13/13] Adjust tests for smoother weary.tracker Some of the test times were being altered by the every-30-minute (awake) weary.tracker reductions. Alter to match new ones, also taking into account local testing (including in scrambled order). While with some scrambled tests am seeing inconsistencies between 8-hour and 12-hour digging, 8-hour without fluctuations indicated 3->4 should not be 470 minutes, but no more than 465 - which it already was for 12-hour, weirdly enough (oops by me earlier?). --- src/character.cpp | 2 +- tests/weary_test.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 71c9bdb4e3771..407ce2401331f 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -5708,7 +5708,7 @@ void Character::try_reduce_weariness( const float exertion ) const float recovery_mult = get_option( "WEARY_RECOVERY_MULT" ); - if( weary.low_activity_ticks > 0 ) { + if( weary.low_activity_ticks >= 1 ) { int reduction = weary.tracker; const int bmr = base_bmr(); // 1/120 of whichever's bigger diff --git a/tests/weary_test.cpp b/tests/weary_test.cpp index 165b53e7fbb17..79f113b9ff6b2 100644 --- a/tests/weary_test.cpp +++ b/tests/weary_test.cpp @@ -72,7 +72,7 @@ TEST_CASE( "weary_assorted_tasks", "[weary][activities][!mayfail]" ) CHECK( info.transition_minutes( 0, 1, 120_minutes ) == Approx( 120 ).margin( 5 ) ); CHECK( info.transition_minutes( 1, 2, 255_minutes ) == Approx( 255 ).margin( 5 ) ); CHECK( info.transition_minutes( 2, 3, 360_minutes ) == Approx( 360 ).margin( 5 ) ); - CHECK( info.transition_minutes( 3, 4, 470_minutes ) == Approx( 470 ).margin( 5 ) ); + CHECK( info.transition_minutes( 3, 4, 465_minutes ) == Approx( 465 ).margin( 5 ) ); CHECK( !info.have_weary_decrease() ); CHECK( guy.weariness_level() == 4 ); } @@ -132,8 +132,8 @@ TEST_CASE( "weary_recovery", "[weary][activities]" ) INFO( info.summarize() ); INFO( guy.debug_weary_info() ); REQUIRE( !info.empty() ); - CHECK( info.transition_minutes( 4, 3, 520_minutes ) == Approx( 520 ).margin( 5 ) ); - CHECK( info.transition_minutes( 3, 2, 640_minutes ) == Approx( 640 ).margin( 5 ) ); + CHECK( info.transition_minutes( 4, 3, 505_minutes ) == Approx( 505 ).margin( 5 ) ); + CHECK( info.transition_minutes( 3, 2, 630_minutes ) == Approx( 630 ).margin( 5 ) ); CHECK( info.transition_minutes( 1, 0, 0_minutes ) > ( 8 * 60 ) ); // should be INT_MAX CHECK( info.transition_minutes( 2, 1, 0_minutes ) > ( 8 * 60 ) ); CHECK( info.transition_minutes( 1, 2, 16_hours ) <= ( 8 * 60 ) ); @@ -153,7 +153,7 @@ TEST_CASE( "weary_recovery", "[weary][activities]" ) CHECK( info.transition_minutes( 0, 1, 325_minutes ) == Approx( 325 ).margin( 5 ) ); CHECK( info.transition_minutes( 1, 2, 625_minutes ) == Approx( 625 ).margin( 5 ) ); CHECK( info.transition_minutes( 2, 1, 740_minutes ) == Approx( 740 ).margin( 5 ) ); - CHECK( info.transition_minutes( 1, 0, 995_minutes ) == Approx( 995 ).margin( 5 ) ); + CHECK( info.transition_minutes( 1, 0, 985_minutes ) == Approx( 985 ).margin( 5 ) ); } }