Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: fahrenheit to celsius in codebase, part 1 #2570

Merged
merged 11 commits into from
Sep 21, 2023
1 change: 0 additions & 1 deletion src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,6 @@ bool game::start_game()
}
u.process_turn(); // process_turn adds the initial move points
u.set_stamina( u.get_stamina_max() );
get_weather().temperature = SPRING_TEMPERATURE;
get_weather().update_weather();
u.next_climate_control_check = calendar::before_time_starts; // Force recheck at startup
u.last_climate_control_ret = false;
Expand Down
41 changes: 16 additions & 25 deletions src/game_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,34 +78,37 @@ static constexpr int PLUTONIUM_CHARGES = 500;
// Temperature constants.
namespace temperatures
{

/// Average annual temperature used for climate, weather and temperature calculation.
constexpr units::temperature annual_average = 6_c;

// temperature at which something starts is considered HOT.
constexpr units::temperature hot = 100_f; // ~ 38 Celsius
constexpr units::temperature hot = 38_c;

// the "normal" temperature midpoint between cold and hot.
constexpr units::temperature normal = 70_f; // ~ 21 Celsius
constexpr units::temperature normal = 21_c;

// Temperature inside an active fridge in Fahrenheit.
constexpr units::temperature fridge = 37_f; // ~ 2.7 Celsius
// Temperature inside an active fridge
constexpr units::temperature fridge = 2_c;

// Temperature at which things are considered "cold".
constexpr units::temperature cold = 40_f; // ~4.4 C
constexpr units::temperature cold = 5_c;

// Temperature inside an active freezer in Fahrenheit.
constexpr units::temperature freezer = 23_f; // -5 Celsius
// Temperature inside an active freezer.
constexpr units::temperature freezer = -5_c;

// Temperature in which water freezes in Fahrenheit.
constexpr units::temperature freezing = 32_f; // 0 Celsius
// Temperature in which water freezes.
constexpr units::temperature freezing = 0_c;

// Arbitrary constant for root cellar temperature
// Should be equal to AVERAGE_ANNUAL_TEMPERATURE, but is declared before it...
constexpr units::temperature root_cellar = 43_f;
constexpr units::temperature root_cellar = annual_average;
} // namespace temperatures

// Weight per level of LIFT/JACK tool quality.
#define TOOL_LIFT_FACTOR 500_kilogram // 500kg/level
static constexpr units::mass TOOL_LIFT_FACTOR = 500_kilogram; // 500kg/level

// Cap JACK requirements to support arbitrarily large vehicles.
#define JACK_LIMIT 8500_kilogram // 8500kg ( 8.5 metric tonnes )
static constexpr units::mass JACK_LIMIT = 8500_kilogram;

// Slowest speed at which a gun can be aimed.
static constexpr int MAX_AIM_COST = 10;
Expand Down Expand Up @@ -139,18 +142,6 @@ static constexpr int BIO_CQB_LEVEL = 5;
// Minimum size of a horde to show up on the minimap.
static constexpr int HORDE_VISIBILITY_SIZE = 3;

/**
* Average annual temperature in F used for climate, weather and temperature calculation.
* Average New England temperature = 43F/6C rounded to int.
*/
static constexpr int AVERAGE_ANNUAL_TEMPERATURE = 43;

/**
* Base starting spring temperature in F used for climate, weather and temperature calculation.
* New England base spring temperature = 65F/18C rounded to int.
*/
static constexpr int SPRING_TEMPERATURE = 65;

/**
* Used to limit the random seed during noise calculation. A large value flattens the noise generator to zero.
* Windows has a rand limit of 32768, other operating systems can have higher limits.
Expand Down
111 changes: 44 additions & 67 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
#include "text_snippets.h"
#include "translations.h"
#include "units.h"
#include "units_temperature.h"
#include "units_utility.h"
#include "value_ptr.h"
#include "vehicle.h"
Expand Down Expand Up @@ -5610,78 +5611,57 @@ int item::spoilage_sort_order() const
return bottom;
}

namespace
{
scarf005 marked this conversation as resolved.
Show resolved Hide resolved

/**
* Food decay calculation.
* Calculate how much food rots per hour, based on 10 = 1 minute of decay @ 65 F.
* Hardcoded lookup table for food rots per hour calculation.
*
* IRL this tends to double every 10c a few degrees above freezing, but past a certain
* point the rate decreases until even extremophiles find it too hot. Here we just stop
* further acceleration at 105 F. This should only need to run once when the game starts.
* @see calc_rot_array
* @see rot_chart
* further acceleration at 40C.
*
* Original formula:
* @see https://github.com/cataclysmbnteam/Cataclysm-BN/blob/033901af4b52ad0bfcfd6abfe06bca4e403d44b1/src/item.cpp#L5612-L5640
*/
static int calc_hourly_rotpoints_at_temp( const int temp )
constexpr auto rot_chart = std::array<int, 44>
{
// default temp = 65, so generic->rotten() assumes 600 decay points per hour
const int dropoff = 38; // ditch our fancy equation and do a linear approach to 0 rot at 31f
const int cutoff = 105; // stop torturing the player at this temperature, which is
const int cutoffrot = 21240; // ..almost 6 times the base rate. bacteria hate the heat too

const int dsteps = dropoff - units::to_fahrenheit( temperatures::freezing );
const int dstep = ( 215.46 * std::pow( 2.0, static_cast<float>( dropoff ) / 16.0 ) / dsteps );

if( temp < units::to_fahrenheit( temperatures::freezing ) ) {
return 0;
} else if( temp > cutoff ) {
return cutoffrot;
} else if( temp < dropoff ) {
return ( temp - units::to_fahrenheit( temperatures::freezing ) ) * dstep;
} else {
return std::lround( 215.46 * std::pow( 2.0, static_cast<float>( temp ) / 16.0 ) );
}
}
0, 372, 744, 1118, 1219, 1273, 1388, 1514, 1651, 1800,
1880, 2050, 2235, 2438, 2658, 2776, 3027, 3301, 3600, 3926,
4100, 4471, 4875, 5317, 5798, 6054, 6602, 7200, 7852, 8562,
8941, 9751, 10633, 11595, 12645, 13205, 14400, 15703, 17125, 18674,
19501,
};

/**
* Initialize the rot table.
* @see rot_chart
*/
static std::vector<int> calc_rot_array( const size_t cap )
{
std::vector<int> ret;
ret.reserve( cap );
for( size_t i = 0; i < cap; ++i ) {
ret.push_back( calc_hourly_rotpoints_at_temp( static_cast<int>( i ) ) );
}
return ret;
}
} // namespace

/**
* Get the hourly rot for a given temperature from the precomputed table.
* @see rot_chart
*/
int get_hourly_rotpoints_at_temp( const int temp )
auto get_hourly_rotpoints_at_temp( const units::temperature temp ) -> int
{
/**
* Precomputed rot lookup table.
*/
static const std::vector<int> rot_chart = calc_rot_array( 200 );

if( temp < 0 ) {
if( temp < temperatures::freezing ) {
return 0;
}
if( temp > 150 ) {
if( temp > 40_c ) {
return 21240;
}
return rot_chart[temp];
const int temp_c = units::to_celsius( temp );
return rot_chart[temp_c];
}

time_duration item::calc_rot( time_point time, int temp ) const
auto item::calc_rot( time_point time, const units::temperature temp ) const -> time_duration
{
// Avoid needlessly calculating already rotten things. Corpses should
// always rot away and food rots away at twice the shelf life. If the food
// is in a sealed container they won't rot away, this avoids needlessly
// calculating their rot in that case.
if( !is_corpse() && get_relative_rot() > 2.0 ) {
return time_duration::from_seconds( 0 );
return 0_seconds;
}

// rot modifier
Expand All @@ -5690,7 +5670,7 @@ time_duration item::calc_rot( time_point time, int temp ) const
factor = 0.75;
}

time_duration added_rot = time_duration::from_seconds( 0 );
time_duration added_rot = 0_seconds;
// simulation of different age of food at the start of the game and good/bad storage
// conditions by applying starting variation bonus/penalty of +/- 20% of base shelf-life
// positive = food was produced some time before calendar::start and/or bad storage
Expand All @@ -5699,34 +5679,38 @@ time_duration item::calc_rot( time_point time, int temp ) const
time_duration spoil_variation = get_shelf_life() * 0.2f;
added_rot += rng( -spoil_variation, spoil_variation );
}

time_duration time_delta = time - last_rot_check;
added_rot += factor * time_delta / 1_hours * get_hourly_rotpoints_at_temp( temp ) * 1_turns;
return added_rot;
}

static int temperature_flag_to_highest_temperature( temperature_flag temperature )
namespace
{

auto temperature_flag_to_highest_temperature( temperature_flag temperature ) -> units::temperature
{
switch( temperature ) {
case temperature_flag::TEMP_NORMAL:
return INT_MAX;
case temperature_flag::TEMP_HEATER:
return INT_MAX;
return units::temperature_max;
case temperature_flag::TEMP_FRIDGE:
return to_fahrenheit( temperatures::fridge );
return temperatures::fridge;
case temperature_flag::TEMP_FREEZER:
return to_fahrenheit( temperatures::freezer );
return temperatures::freezer;
case temperature_flag::TEMP_ROOT_CELLAR:
return to_fahrenheit( temperatures::root_cellar );
return temperatures::root_cellar;
}

return INT_MAX;
return units::temperature_max;
}

} // namespace


time_duration item::minimum_freshness_duration( temperature_flag temperature ) const
{
int temperature_f = temperature_flag_to_highest_temperature( temperature );
unsigned long long rot_per_hour = get_hourly_rotpoints_at_temp( temperature_f );
const units::temperature temp = temperature_flag_to_highest_temperature( temperature );
unsigned long long rot_per_hour = get_hourly_rotpoints_at_temp( temp );

if( rot_per_hour <= 0 || !type->comestible ) {
return calendar::INDEFINITELY_LONG_DURATION;
Expand Down Expand Up @@ -9008,7 +8992,7 @@ bool item::process_rot( const bool seals, const tripoint &pos,

// process rot at most once every 100_turns (10 min)
// note we're also gated by item::processing_speed
time_duration smallest_interval = 10_minutes;
constexpr time_duration smallest_interval = 10_minutes;

units::temperature temp = units::from_fahrenheit( weather.get_temperature( pos ) );
temp = clip_by_temperature_flag( temp, flag );
Expand Down Expand Up @@ -9040,17 +9024,13 @@ bool item::process_rot( const bool seals, const tripoint &pos,
calendar::config, seed );
env_temperature_raw = weather_temperature + local_mod;
} else {
env_temperature_raw = units::from_fahrenheit( AVERAGE_ANNUAL_TEMPERATURE ) + local_mod;
env_temperature_raw = temperatures::annual_average + local_mod;
}

units::temperature env_temperature_clipped = clip_by_temperature_flag( env_temperature_raw, flag );

// Lookup table is in F
int final_temperature_in_fahrenheit = static_cast<int>( std::round( units::to_fahrenheit<float>
( env_temperature_clipped ) ) );

// Calculate item rot
rot += calc_rot( time, final_temperature_in_fahrenheit );
rot += calc_rot( time, env_temperature_clipped );
last_rot_check = time;

if( has_rotten_away() && carrier == nullptr && !seals ) {
Expand All @@ -9063,10 +9043,7 @@ bool item::process_rot( const bool seals, const tripoint &pos,
// Remaining <1 h from above
// and items that are held near the player
if( now - time > smallest_interval ) {
int final_temperature_in_fahrenheit = static_cast<int>( std::round( units::to_fahrenheit<float>
( temp ) ) );

rot += calc_rot( now, final_temperature_in_fahrenheit );
rot += calc_rot( now, temp );
last_rot_check = now;

return has_rotten_away() && carrier == nullptr && !seals;
Expand Down
2 changes: 1 addition & 1 deletion src/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@ class item : public visitable<item>
* @param time Time point to which rot is calculated
* @param temp Temperature at which the rot is calculated
*/
time_duration calc_rot( time_point time, int temp ) const;
auto calc_rot( time_point time, const units::temperature temp ) const -> time_duration;

/**
* Time that this item is guaranteed to stay fresh.
Expand Down
2 changes: 1 addition & 1 deletion src/timed_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ void timed_event::per_turn()
}
}

if( calendar::once_every( time_duration::from_seconds( 10 ) ) && faults ) {
if( calendar::once_every( 10_seconds ) && faults ) {
add_msg( m_info, "You hear someone whispering \"%s\"",
SNIPPET.random_from_category( "amigara_whispers" ).value_or( translation() ) );
}
Expand Down
5 changes: 5 additions & 0 deletions src/units_temperature.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ inline constexpr units::temperature operator"" _c( const unsigned long long v )
return units::from_celsius<int>( v );
}

inline constexpr units::temperature operator"" _c( const long double v )
{
return units::from_celsius<double>( static_cast<double>( v ) );
}

inline constexpr units::temperature operator"" _f( const unsigned long long v )
{
return units::from_fahrenheit<int>( v );
Expand Down
Loading
Loading