Skip to content

Commit

Permalink
Extract activity and weariness tracking to a helper class.
Browse files Browse the repository at this point in the history
  • Loading branch information
kevingranade committed Mar 24, 2021
1 parent b991a1b commit ac8bae1
Show file tree
Hide file tree
Showing 17 changed files with 397 additions and 282 deletions.
155 changes: 155 additions & 0 deletions src/activity_tracker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#include "activity_tracker.h"

#include "game_constants.h"
#include "options.h"
#include "string_formatter.h"

int activity_tracker::weariness() const
{
if( intake > tracker ) {
return tracker * 0.5;
}
return tracker - intake * 0.5;
}

// Called every 5 minutes, when activity level is logged
void activity_tracker::try_reduce_weariness( int bmr, bool sleeping )
{
tick_counter++;
if( average_activity() - NO_EXERCISE <= std::numeric_limits<float>::epsilon() ) {
low_activity_ticks++;
// Recover twice as fast at rest
if( sleeping ) {
low_activity_ticks++;
}
}

const float recovery_mult = get_option<float>( "WEARY_RECOVERY_MULT" );

if( low_activity_ticks >= 6 ) {
int reduction = tracker;
// 1/20 of whichever's bigger
if( bmr > reduction ) {
reduction = bmr * recovery_mult;
} else {
reduction *= recovery_mult;
}
low_activity_ticks -= 6;

tracker -= reduction;
}

if( tick_counter >= 12 ) {
intake *= 1 - recovery_mult;
tick_counter -= 12;
}

// Normalize values, make sure we stay above 0
intake = std::max( intake, 0 );
tracker = std::max( tracker, 0 );
tick_counter = std::max( tick_counter, 0 );
low_activity_ticks = std::max( low_activity_ticks, 0 );
}

void activity_tracker::weary_clear()
{
tracker = 0;
intake = 0;
low_activity_ticks = 0;
tick_counter = 0;
}

std::string activity_tracker::debug_weary_info() const
{
return string_format( "Intake: %d Tracker: %d", intake, tracker );
}

void activity_tracker::calorie_adjust( int nkcal )
{
if( nkcal > 0 ) {
intake += nkcal;
} else {
// nkcal is negative, we need positive
tracker -= nkcal;
}
}

float activity_tracker::activity() const
{
if( current_turn == calendar::turn ) {
return current_activity;
}
return 1.0f;
}

float activity_tracker::average_activity() const
{
if( activity_reset && current_turn != calendar::turn ) {
return previous_activity / num_events;
}
return ( accumulated_activity + current_activity ) / num_events;
}

float activity_tracker::instantaneous_activity_level() const
{
if( current_turn == calendar::turn ) {
return current_activity;
}
return previous_turn_activity;
}

// The idea here is the character is going about their business logging activities,
// and log_activity() handles sorting them out, it records the largest magnitude for a given turn,
// and then rolls the previous turn's value into the accumulator once a new activity is logged.
// After a reset, we have to pretend the previous values weren't logged.
void activity_tracker::log_activity( float new_level )
{
current_activity = std::max( current_activity, new_level );
current_turn = calendar::turn;
}

void activity_tracker::new_turn()
{
if( activity_reset ) {
activity_reset = false;
previous_turn_activity = current_activity;
current_activity = NO_EXERCISE;
accumulated_activity = 0.0f;
num_events = 1;
} else {
// This is for the last turn that had activity logged.
accumulated_activity += current_activity;
// Then handle the interventing turns that had no activity logged.
int num_turns = to_turns<int>( calendar::turn - current_turn );
if( num_turns > 1 ) {
accumulated_activity += ( num_turns - 1 ) * NO_EXERCISE;
num_events += num_turns - 1;
}
previous_turn_activity = current_activity;
current_activity = NO_EXERCISE;
num_events++;
}
}

void activity_tracker::reset_activity_level()
{
previous_activity = accumulated_activity;
activity_reset = true;
}

std::string activity_tracker::activity_level_str() const
{
if( current_activity <= NO_EXERCISE ) {
return _( "NO_EXERCISE" );
} else if( current_activity <= LIGHT_EXERCISE ) {
return _( "LIGHT_EXERCISE" );
} else if( current_activity <= MODERATE_EXERCISE ) {
return _( "MODERATE_EXERCISE" );
} else if( current_activity <= BRISK_EXERCISE ) {
return _( "BRISK_EXERCISE" );
} else if( current_activity <= ACTIVE_EXERCISE ) {
return _( "ACTIVE_EXERCISE" );
} else {
return _( "EXTRA_EXERCISE" );
}
}
54 changes: 54 additions & 0 deletions src/activity_tracker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#pragma once
#ifndef CATA_SRC_ACTIVITY_TRACKER_H
#define CATA_SRC_ACTIVITY_TRACKER_H

#include "calendar.h"

class JsonIn;
class JsonOut;

class activity_tracker
{
private:
float current_activity = 0.0;
float accumulated_activity = 0.0;
float previous_activity = 0.0;
float previous_turn_activity = 0.0;
time_point current_turn = calendar::turn_zero;
bool activity_reset = false;
int num_events = 0;

// Weariness metadata.
int tracker = 0;
int intake = 0;
// Semi-consecutive 5 minute ticks of low activity (or 2.5 if we're sleeping)
int low_activity_ticks = 0;
// How many ticks since we've decreased intake
int tick_counter = 0;
public:
// Logs activity level. If called multiple times in one turn, will preserve the highest.
void log_activity( float new_level );
// Informs the tracker that a new turn has started.
void new_turn();
// Resets accumulated activity level.
void reset_activity_level();
// outputs player activity level to a printable string
std::string activity_level_str() const;
// Returns activity level recorded for the current turn.
float activity() const;
// Returns average of activity level for the current period.
float average_activity() const;
// Returns the previous turn's activity level until an action is tanken on the current turn.
float instantaneous_activity_level() const;

int weariness() const;
void try_reduce_weariness( int bmr, bool sleeping );
void calorie_adjust( int nkcal );
void weary_clear();
std::string debug_weary_info() const;

void serialize( JsonOut &json ) const;
void deserialize( JsonIn &jsin );
};

#endif // CATA_SRC_ACTIVITY_TRACKER_H
2 changes: 1 addition & 1 deletion src/avatar_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ bool avatar_action::move( avatar &you, map &m, const tripoint &d )

// by this point we're either walking, running, crouching, or attacking, so update the activity level to match
if( !is_riding ) {
you.increase_activity_level( you.current_movement_mode()->exertion_level() );
you.set_activity_level( you.current_movement_mode()->exertion_level() );
}

// If the player is *attempting to* move on the X axis, update facing direction of their sprite to match.
Expand Down
Loading

0 comments on commit ac8bae1

Please sign in to comment.