Skip to content

Commit

Permalink
Eating same food repeatedly gives less fun
Browse files Browse the repository at this point in the history
Introduces a new JSON comestible property, "monotony_penalty", that is
subtracted from a food item's fun score for every food like it you've
eaten in the last 48 hours. The penalty can't take a food's fun below 0
or reduce fun for foods that already had negative fun, unless
that food has the "NEGATIVE_MONOTONY_OK" flag.
Default "monotony_penalty" is 2, except for junk food where it's 0.
  • Loading branch information
Davi-DeGanne committed Dec 6, 2019
1 parent f04c6d5 commit 91e8a62
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 5 deletions.
1 change: 1 addition & 0 deletions doc/JSON_FLAGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ Some armor flags, such as `WATCH` and `ALARMCLOCK` are compatible with other ite
- ```MELTS``` Provides half fun unless frozen. Edible when frozen.
- ```MILLABLE``` Can be placed inside a mill, to turn into flour.
- ```MYCUS_OK``` Can be eaten by post-threshold Mycus characters. Only applies to mycus fruits by default.
- ```NEGATIVE_MONOTONY_OK``` Allows ```negative_monotony``` property to lower comestible fun to negative values.
- ```NO_INGEST``` Administered by some means other than oral intake.
- ```PKILL_1``` Minor painkiller.
- ```PKILL_2``` Moderate painkiller.
Expand Down
2 changes: 2 additions & 0 deletions doc/JSON_INFO.md
Original file line number Diff line number Diff line change
Expand Up @@ -1367,6 +1367,8 @@ CBMs can be defined like this:
"quench" : 0, // Thirst quenched
"heal" : -2, // Health effects (used for sickness chances)
"addiction_potential" : 80, // Ability to cause addictions
"monotony_penalty" : 0, // (Optional, default: 2) Fun is reduced by this number for each one you've consumed in the last 48 hours.
// Can't drop fun below 0, unless the comestible also has the "NEGATIVE_MONOTONY_OK" flag.
"calories" : 0, // Hunger satisfied (in kcal)
"nutrition" : 0, // Hunger satisfied (OBSOLETE)
"tool" : "apparatus", // Tool required to be eaten/drank
Expand Down
1 change: 1 addition & 0 deletions src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,7 @@ class Character : public Creature, public visitable<Character>

stomach_contents stomach;
stomach_contents guts;
std::list<std::pair<const time_point, const item *>> consumption_history;

int oxygen;
int radiation;
Expand Down
21 changes: 21 additions & 0 deletions src/consumption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,20 @@ std::pair<int, int> Character::fun_for( const item &comest ) const
}
}

// Food is less enjoyable when eaten too often.
if( fun > 0 || comest.has_flag( "NEGATIVE_MONOTONY_OK" ) ) {
for( const std::pair<const time_point, const item *> &event : consumption_history ) {
if( event.first > calendar::turn - 2_days && event.second->typeId() == comest.typeId() ) {
fun -= comest.get_comestible()->monotony_penalty;
// This effect can't drop fun below 0, unless the food has the right flag.
if( fun <= 0 && !comest.has_flag( "NEGATIVE_MONOTONY_OK" ) ) {
fun = 0;
break; // 0 is the lowest we'll go, no need to keep looping.
}
}
}
}

float fun_max = fun < 0 ? fun * 6 : fun * 3;
if( comest.has_flag( flag_EATEN_COLD ) && comest.has_flag( flag_COLD ) ) {
if( fun > 0 ) {
Expand Down Expand Up @@ -952,6 +966,13 @@ bool player::eat( item &food, bool force )
if( will_vomit ) {
vomit();
}

consumption_history.emplace_back( calendar::turn, &food );
// Clean out consumption_history so it doesn't get bigger than needed.
while( consumption_history.front().first < calendar::turn - 2_days ) {
consumption_history.pop_front();
}

return true;
}

Expand Down
17 changes: 12 additions & 5 deletions src/item_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1684,12 +1684,13 @@ void Item_factory::load( islot_comestible &slot, JsonObject &jo, const std::stri
assign( jo, "cooks_like", slot.cooks_like, strict );
assign( jo, "smoking_result", slot.smoking_result, strict );

bool is_junkfood = false;
if( jo.has_member( "primary_material" ) ) {
slot.specific_heat_solid = material_id(
jo.get_string( "primary_material" ) )->specific_heat_solid();
slot.specific_heat_liquid = material_id(
jo.get_string( "primary_material" ) )->specific_heat_liquid();
slot.latent_heat = material_id( jo.get_string( "primary_material" ) )->latent_heat();
std::string mat = jo.get_string( "primary_material" );
slot.specific_heat_solid = material_id( mat )->specific_heat_solid();
slot.specific_heat_liquid = material_id( mat )->specific_heat_liquid();
slot.latent_heat = material_id( mat )->latent_heat();
is_junkfood = is_junkfood || mat == "junk";
} else if( jo.has_member( "material" ) ) {
float specific_heat_solid = 0;
float specific_heat_liquid = 0;
Expand All @@ -1699,13 +1700,19 @@ void Item_factory::load( islot_comestible &slot, JsonObject &jo, const std::stri
specific_heat_solid += material_id( m )->specific_heat_solid();
specific_heat_liquid += material_id( m )->specific_heat_liquid();
latent_heat += material_id( m )->latent_heat();
is_junkfood = is_junkfood || m == "junk";
}
// Average based on number of materials.
slot.specific_heat_liquid = specific_heat_liquid / jo.get_tags( "material" ).size();
slot.specific_heat_solid = specific_heat_solid / jo.get_tags( "material" ).size();
slot.latent_heat = latent_heat / jo.get_tags( "material" ).size();
}

if( is_junkfood ) { // Junk food never gets old by default, but this can still be overriden.
slot.monotony_penalty = 0;
}
assign( jo, "monotony_penalty", slot.monotony_penalty, strict );

if( jo.has_string( "addiction_type" ) ) {
slot.add = addiction_type( jo.get_string( "addiction_type" ) );
}
Expand Down
3 changes: 3 additions & 0 deletions src/itype.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ struct islot_comestible {
float specific_heat_solid = 2.108;
float latent_heat = 333;

/** A penalty applied to fun for every time this food has been eaten in the last 48 hours */
int monotony_penalty = 2;

/** vitamins potentially provided by this comestible (if any) */
std::map<vitamin_id, int> vitamins;

Expand Down

0 comments on commit 91e8a62

Please sign in to comment.