From a1b5d6dbc13d185b9ac459e421ae44b3ef8ce133 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Sun, 3 Dec 2017 22:04:25 +0100 Subject: [PATCH] lose weight through exercise --- assets | 2 +- src/app/app.cpp | 3 +++ src/creature/Composition.hpp | 8 ++++---- src/creature/Creature.hpp | 3 +++ src/creature/Situation.hpp | 2 +- src/creature/creature.cpp | 38 +++++++++++++++++++++++++++++------- src/creature/goal.cpp | 9 +++++---- src/world/Resource.hpp | 2 ++ 8 files changed, 50 insertions(+), 17 deletions(-) diff --git a/assets b/assets index 3c715b3..7b1b41f 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 3c715b39e3aece21fc1f0fd6042611e79bfbeb44 +Subproject commit 7b1b41f192be522bc6812db7e91798c2fee0e5e1 diff --git a/src/app/app.cpp b/src/app/app.cpp index a732ca6..3f87c8f 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -251,6 +251,9 @@ void Assets::ReadResources(io::TokenStreamReader &in) { in.ReadString(data.resources[id].label); } else if (name == "density") { data.resources[id].density = in.GetDouble(); + } else if (name == "energy") { + data.resources[id].energy = in.GetDouble(); + data.resources[id].inverse_energy = 1.0 / data.resources[id].energy; } else if (name == "state") { in.ReadIdentifier(name); if (name == "solid") { diff --git a/src/creature/Composition.hpp b/src/creature/Composition.hpp index 621f640..c062334 100644 --- a/src/creature/Composition.hpp +++ b/src/creature/Composition.hpp @@ -21,11 +21,11 @@ public: Composition(); ~Composition(); - Composition(const Composition &) = delete; - Composition &operator =(const Composition &) = delete; + Composition(const Composition &) = default; + Composition &operator =(const Composition &) = default; - Composition(Composition &&) = delete; - Composition &operator =(Composition &&) = delete; + Composition(Composition &&) = default; + Composition &operator =(Composition &&) = default; public: void Add(int res, double amount); diff --git a/src/creature/Creature.hpp b/src/creature/Creature.hpp index 3f86670..4d16f99 100644 --- a/src/creature/Creature.hpp +++ b/src/creature/Creature.hpp @@ -105,6 +105,8 @@ public: double Mass() const noexcept { return mass; } void Ingest(int res, double amount) noexcept; + void DoWork(double amount) noexcept; + void Size(double s) noexcept { size = s; } double Size() const noexcept { return size; } @@ -113,6 +115,7 @@ public: /// age-depended multiplier, peak being the maximum in lifetime [0,1] double AgeFactor(double peak) const noexcept; + double EnergyEfficiency() const noexcept; double ExhaustionFactor() const noexcept; double FatigueFactor() const noexcept; diff --git a/src/creature/Situation.hpp b/src/creature/Situation.hpp index 3c4a28a..4d635f5 100644 --- a/src/creature/Situation.hpp +++ b/src/creature/Situation.hpp @@ -64,7 +64,7 @@ public: const State &GetState() const noexcept { return state; } const glm::dvec3 &Velocity() const noexcept { return state.vel; } - bool Moving() const noexcept { return glm::length2(state.vel) > 0.0000001; } + bool Moving() const noexcept { return glm::length2(state.vel) > 0.000001; } void Move(const glm::dvec3 &dp) noexcept; void Accelerate(const glm::dvec3 &dv) noexcept; void EnforceConstraints(State &) noexcept; diff --git a/src/creature/creature.cpp b/src/creature/creature.cpp index fb6e9f6..9ef8dd9 100644 --- a/src/creature/creature.cpp +++ b/src/creature/creature.cpp @@ -45,14 +45,17 @@ bool CompositionCompare(const Composition::Component &a, const Composition::Comp void Composition::Add(int res, double amount) { bool found = false; - for (auto &c : components) { - if (c.resource == res) { - c.value += amount; + for (auto c = components.begin(); c != components.end(); ++c) { + if (c->resource == res) { + c->value += amount; + if (c->value <= 0.0) { + components.erase(c); + } found = true; break; } } - if (!found) { + if (!found && amount > 0.0) { components.emplace_back(res, amount); } std::sort(components.begin(), components.end(), CompositionCompare); @@ -138,6 +141,20 @@ void Creature::Ingest(int res, double amount) noexcept { } } +void Creature::DoWork(double amount) noexcept { + stats.Exhaustion().Add(amount / Stamina()); + // burn resources proportional to composition + // factor = 1/total * 1/efficiency * amount * -1 + double factor = -amount / (composition.TotalMass() * EnergyEfficiency()); + // make a copy to total remains constant and + // no entries disappear during iteration + Composition comp(composition); + for (auto &cmp : comp) { + double value = cmp.value * factor * sim.Resources()[cmp.resource].inverse_energy; + AddMass(cmp.resource, value); + } +} + void Creature::Hurt(double amount) noexcept { stats.Damage().Add(amount); if (stats.Damage().Full()) { @@ -194,7 +211,12 @@ double Creature::AgeFactor(double peak) const noexcept { // shifted inverse hermite, y = 1 - (3t² - 2t³) with t = normalized age - peak // goes negative below -0.5 and starts to rise again above 1.0 double t = glm::clamp((Age() / properties.Lifetime()) - peak, -0.5, 1.0); - return 1.0 - (3.0 * t * t) + (2.0 * t * t * t); + // guarantee at least 1% + return std::max(0.01, 1.0 - (3.0 * t * t) + (2.0 * t * t * t)); +} + +double Creature::EnergyEfficiency() const noexcept { + return 0.25 * AgeFactor(0.05); } double Creature::ExhaustionFactor() const noexcept { @@ -293,7 +315,8 @@ void Creature::TickState(double dt) { } } situation.SetState(state); - stats.Exhaustion().Add(length(f.acc) * Mass() / Stamina() * 0.5 * dt); + // work is force times distance + DoWork(length(f.acc) * Mass() * length(f.vel) * dt); } Situation::Derivative Creature::Step(const Situation::Derivative &ds, double dt) const noexcept { @@ -835,7 +858,8 @@ glm::dvec3 Steering::Force(const Situation::State &s) const noexcept { SumForce(result, repulse, force); } if (halting) { - SumForce(result, s.vel * -force, force); + // break twice as hard + SumForce(result, s.vel * force * -2.0, force); } if (seeking) { glm::dvec3 diff = target - s.pos; diff --git a/src/creature/goal.cpp b/src/creature/goal.cpp index f3e0891..5f9f1e8 100644 --- a/src/creature/goal.cpp +++ b/src/creature/goal.cpp @@ -6,6 +6,7 @@ #include "Creature.hpp" #include "../app/Assets.hpp" +#include "../ui/String.hpp" #include "../world/Planet.hpp" #include "../world/Resource.hpp" #include "../world/Simulation.hpp" @@ -41,9 +42,9 @@ void BlobBackgroundTask::Tick(double dt) { // TODO: check if in compatible atmosphere double amount = GetCreature().GetStats().Breath().gain * -(1.5 + 0.5 * GetCreature().ExhaustionFactor()); GetCreature().GetStats().Breath().Add(amount * dt); - // maintain ~2.5% gas composition + // maintain ~1% gas composition double gas_amount = GetCreature().GetComposition().Get(gas); - if (gas_amount < GetCreature().GetComposition().TotalMass() * 0.025) { + if (gas_amount < GetCreature().GetComposition().TotalMass() * 0.01) { double add = std::min(GetCreature().GetComposition().TotalMass() * 0.025 - gas_amount, -amount * dt); GetCreature().Ingest(gas, add); } @@ -99,8 +100,8 @@ void BlobBackgroundTask::CheckStats() { void BlobBackgroundTask::CheckSplit() { if (GetCreature().Mass() > GetCreature().OffspringMass() * 2.0 && GetCreature().OffspringChance() > Assets().random.UNorm()) { - std::cout << "[" << int(GetCreature().GetSimulation().Time()) - << "s] " << GetCreature().Name() << " split" << std::endl; + std::cout << "[" << ui::TimeString(GetCreature().GetSimulation().Time()) + << "] " << GetCreature().Name() << " split" << std::endl; Split(GetCreature()); return; } diff --git a/src/world/Resource.hpp b/src/world/Resource.hpp index 3abe8f3..ad729c8 100644 --- a/src/world/Resource.hpp +++ b/src/world/Resource.hpp @@ -15,6 +15,8 @@ struct Resource { std::string label = ""; double density = 1.0; + double energy = 1.0; + double inverse_energy = 1.0; int id = -1; -- 2.39.2