From c49dd02dfabb123e0c6c4b49f761ce6578dfc464 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Sat, 9 Dec 2017 21:39:44 +0100 Subject: [PATCH] ingest forgein materials --- assets | 2 +- src/app/app.cpp | 18 +++++++++++++++ src/creature/Composition.hpp | 7 ++++++ src/creature/LocateResourceGoal.hpp | 2 ++ src/creature/creature.cpp | 36 +++++++++++++++++++++++++---- src/creature/goal.cpp | 25 +++++++++++++++----- src/ui/CreaturePanel.hpp | 1 + src/ui/ui.cpp | 18 ++++++++++----- src/world/Resource.hpp | 3 +++ 9 files changed, 95 insertions(+), 17 deletions(-) diff --git a/assets b/assets index 7b1b41f..f2587b6 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 7b1b41f192be522bc6812db7e91798c2fee0e5e1 +Subproject commit f2587b6b95d73b9b2d2d871e9a8f5b5dae702965 diff --git a/src/app/app.cpp b/src/app/app.cpp index 913f9f2..f847a79 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -269,6 +269,24 @@ void Assets::ReadResources(io::TokenStreamReader &in) { } } else if (name == "base_color") { in.ReadVec(data.resources[id].base_color); + } else if (name == "compatibility") { + in.Skip(io::Token::ANGLE_BRACKET_OPEN); + while (in.Peek().type != io::Token::ANGLE_BRACKET_CLOSE) { + in.ReadIdentifier(name); + int sub_id = 0; + if (data.resources.Has(name)) { + sub_id = data.resources[name].id; + } else { + world::Resource res; + res.name = name; + sub_id = data.resources.Add(res); + } + in.Skip(io::Token::COLON); + double value = in.GetDouble(); + in.Skip(io::Token::SEMICOLON); + data.resources[id].compatibility[sub_id] = value; + } + in.Skip(io::Token::ANGLE_BRACKET_CLOSE); } else { throw std::runtime_error("unknown resource property '" + name + "'"); } diff --git a/src/creature/Composition.hpp b/src/creature/Composition.hpp index c062334..da66992 100644 --- a/src/creature/Composition.hpp +++ b/src/creature/Composition.hpp @@ -1,10 +1,15 @@ #ifndef BLOBLS_CREATURE_COMPOSITION_HPP_ #define BLOBLS_CREATURE_COMPOSITION_HPP_ +#include "../world/Set.hpp" + #include namespace blobs { +namespace world { + class Resource; +} namespace creature { class Composition { @@ -31,6 +36,8 @@ public: void Add(int res, double amount); bool Has(int res) const noexcept; double Get(int res) const noexcept; + double Proportion(int res) const noexcept; + double Compatibility(const world::Set &, int res) const noexcept; double TotalMass() const noexcept { return total_mass; } public: diff --git a/src/creature/LocateResourceGoal.hpp b/src/creature/LocateResourceGoal.hpp index 010b313..bbb636e 100644 --- a/src/creature/LocateResourceGoal.hpp +++ b/src/creature/LocateResourceGoal.hpp @@ -16,6 +16,7 @@ public: ~LocateResourceGoal() noexcept override; public: + void SetMinimum(double m) noexcept { minimum = m; } void Accept(int resource, double attractiveness); std::string Describe() const override; @@ -36,6 +37,7 @@ private: glm::dvec3 target_pos; bool searching; double reevaluate; + double minimum; }; diff --git a/src/creature/creature.cpp b/src/creature/creature.cpp index 396385e..536144b 100644 --- a/src/creature/creature.cpp +++ b/src/creature/creature.cpp @@ -80,6 +80,35 @@ double Composition::Get(int res) const noexcept { return 0.0; } +double Composition::Proportion(int res) const noexcept { + return Get(res) / TotalMass(); +} + +double Composition::Compatibility(const world::Set &resources, int res) const noexcept { + if (Has(res)) { + return Proportion(res); + } + double max_compat = -1.0; + double min_compat = 1.0; + for (const auto &c : components) { + double prop = c.value / TotalMass(); + for (const auto &compat : resources[c.resource].compatibility) { + double value = compat.second * prop; + if (value > max_compat) { + max_compat = value; + } + if (value < min_compat) { + min_compat = value; + } + } + } + if (min_compat < 0.0) { + return min_compat; + } else { + return max_compat; + } +} + Creature::Creature(world::Simulation &sim) : sim(sim) @@ -131,13 +160,12 @@ void Creature::HighlightColor(const glm::dvec3 &c) noexcept { } void Creature::Ingest(int res, double amount) noexcept { - // TODO: check foreign materials if (sim.Resources()[res].state == world::Resource::SOLID) { - // 15% of solids stays in body - AddMass(res, amount * 0.15); + // 30% of solids stays in body + AddMass(res, amount * 0.3 * composition.Compatibility(sim.Resources(), res)); } else { // 10% of fluids stays in body - AddMass(res, amount * 0.05); + AddMass(res, amount * 0.1 * composition.Compatibility(sim.Resources(), res)); } math::GaloisLFSR &random = sim.Assets().random; if (random.UNorm() < AdaptChance()) { diff --git a/src/creature/goal.cpp b/src/creature/goal.cpp index 2d4347c..55fa6c9 100644 --- a/src/creature/goal.cpp +++ b/src/creature/goal.cpp @@ -72,7 +72,13 @@ void BlobBackgroundTask::CheckStats() { drink_subtask = new IngestGoal(GetCreature(), stats.Thirst()); for (const auto &cmp : GetCreature().GetComposition()) { if (Assets().data.resources[cmp.resource].state == world::Resource::LIQUID) { - drink_subtask->Accept(cmp.resource, 1.0); + double value = cmp.value / GetCreature().GetComposition().TotalMass(); + drink_subtask->Accept(cmp.resource, value); + for (const auto &compat : Assets().data.resources[cmp.resource].compatibility) { + if (Assets().data.resources[compat.first].state == world::Resource::LIQUID) { + drink_subtask->Accept(compat.first, value * compat.second); + } + } } } drink_subtask->WhenComplete([&](Goal &) { drink_subtask = nullptr; }); @@ -83,7 +89,13 @@ void BlobBackgroundTask::CheckStats() { eat_subtask = new IngestGoal(GetCreature(), stats.Hunger()); for (const auto &cmp : GetCreature().GetComposition()) { if (Assets().data.resources[cmp.resource].state == world::Resource::SOLID) { - eat_subtask->Accept(cmp.resource, 1.0); + double value = cmp.value / GetCreature().GetComposition().TotalMass(); + eat_subtask->Accept(cmp.resource, value); + for (const auto &compat : Assets().data.resources[cmp.resource].compatibility) { + if (Assets().data.resources[compat.first].state == world::Resource::SOLID) { + eat_subtask->Accept(compat.first, value * compat.second); + } + } } } eat_subtask->WhenComplete([&](Goal &) { eat_subtask = nullptr; }); @@ -286,8 +298,7 @@ void IngestGoal::Tick(double dt) { } if (ingesting) { if (OnSuitableTile() && !GetSituation().Moving()) { - // TODO: determine satisfaction factor - GetCreature().Ingest(resource, yield * dt); + GetCreature().Ingest(resource, yield * GetCreature().GetComposition().Compatibility(Assets().data.resources, resource) * dt); stat.Add(-1.0 * yield * dt); if (stat.Empty()) { SetComplete(); @@ -321,6 +332,7 @@ void IngestGoal::Action() { for (const auto &c : accept) { locate_subtask->Accept(c.resource, c.value); } + locate_subtask->SetMinimum(stat.gain * -1.1); locate_subtask->Urgency(Urgency() + 0.1); locate_subtask->WhenComplete([&](Goal &){ locate_subtask = nullptr; }); GetCreature().AddGoal(std::unique_ptr(locate_subtask)); @@ -350,7 +362,8 @@ LocateResourceGoal::LocateResourceGoal(Creature &c) , found(false) , target_pos(0.0) , searching(false) -, reevaluate(0.0) { +, reevaluate(0.0) +, minimum(0.0) { } LocateResourceGoal::~LocateResourceGoal() noexcept { @@ -478,7 +491,7 @@ void LocateResourceGoal::SearchVicinity() { } } - if (best_rating > 0.0) { + if (best_rating > minimum) { found = true; searching = false; target_pos = glm::normalize(pos + (double(best_pos.x) * step_x) + (double(best_pos.y) * step_y)) * planet.Radius(); diff --git a/src/ui/CreaturePanel.hpp b/src/ui/CreaturePanel.hpp index be12348..7a96bf8 100644 --- a/src/ui/CreaturePanel.hpp +++ b/src/ui/CreaturePanel.hpp @@ -53,6 +53,7 @@ private: Label *born; Label *age; Label *mass; + Label *size; Label *goal; Label *pos; Label *tile; diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 98445b4..dc17b2b 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -29,6 +29,7 @@ CreaturePanel::CreaturePanel(app::Assets &assets) , born(new Label(assets.fonts.medium)) , age(new Label(assets.fonts.medium)) , mass(new Label(assets.fonts.medium)) +, size(new Label(assets.fonts.medium)) , goal(new Label(assets.fonts.medium)) , pos(new Label(assets.fonts.medium)) , tile(new Label(assets.fonts.medium)) @@ -45,6 +46,8 @@ CreaturePanel::CreaturePanel(app::Assets &assets) age_label->Text("Age"); Label *mass_label = new Label(assets.fonts.medium); mass_label->Text("Mass"); + Label *size_label = new Label(assets.fonts.medium); + size_label->Text("Size"); Label *goal_label = new Label(assets.fonts.medium); goal_label->Text("Goal"); @@ -55,6 +58,7 @@ CreaturePanel::CreaturePanel(app::Assets &assets) ->Add(born_label) ->Add(age_label) ->Add(mass_label) + ->Add(size_label) ->Add(goal_label); Panel *info_value_panel = new Panel; info_value_panel @@ -63,6 +67,7 @@ CreaturePanel::CreaturePanel(app::Assets &assets) ->Add(born) ->Add(age) ->Add(mass) + ->Add(size) ->Add(goal); Panel *info_panel = new Panel; info_panel @@ -189,7 +194,6 @@ CreaturePanel::~CreaturePanel() { void CreaturePanel::Show(creature::Creature &cr) { c = &cr; - name->Text(c->Name()); born->Text(TimeString(c->Born())); if (c->Parents().empty()) { @@ -216,8 +220,10 @@ void CreaturePanel::Hide() noexcept { void CreaturePanel::Draw(graphics::Viewport &viewport) noexcept { if (!c) return; + name->Text(c->Name()); age->Text(TimeString(c->Age())); mass->Text(MassString(c->Mass())); + size->Text(LengthString(c->Size())); if (c->Goals().empty()) { goal->Text("none"); } else { @@ -265,12 +271,12 @@ void CreaturePanel::Draw(graphics::Viewport &viewport) noexcept { } } - props[0]->Text(DecimalString(c->Strength(), 2)); - props[1]->Text(DecimalString(c->Stamina(), 2)); - props[2]->Text(DecimalString(c->Dexerty(), 2)); - props[3]->Text(DecimalString(c->Intelligence(), 2)); + props[0]->Text(DecimalString(c->Strength(), 2) + " / " + DecimalString(c->GetProperties().Strength(), 2)); + props[1]->Text(DecimalString(c->Stamina(), 2) + " / " + DecimalString(c->GetProperties().Stamina(), 2)); + props[2]->Text(DecimalString(c->Dexerty(), 2) + " / " + DecimalString(c->GetProperties().Dexerty(), 2)); + props[3]->Text(DecimalString(c->Intelligence(), 2) + " / " + DecimalString(c->GetProperties().Intelligence(), 2)); props[4]->Text(TimeString(c->Lifetime())); - props[5]->Text(PercentageString(c->Fertility())); + props[5]->Text(PercentageString(c->Fertility()) + " / " + PercentageString(c->GetProperties().Fertility())); props[6]->Text(PercentageString(c->Mutability())); props[7]->Text(PercentageString(c->Adaptability())); props[8]->Text(MassString(c->OffspringMass())); diff --git a/src/world/Resource.hpp b/src/world/Resource.hpp index ad729c8..17df324 100644 --- a/src/world/Resource.hpp +++ b/src/world/Resource.hpp @@ -3,6 +3,7 @@ #include "../math/glm.hpp" +#include #include @@ -32,6 +33,8 @@ struct Resource { glm::dvec3 base_color = glm::dvec3(1.0); + std::map compatibility; + }; } -- 2.39.2