#define BLOBLS_CREATURE_COMPOSITION_HPP_
#include "../world/Set.hpp"
+#include "../world/Resource.hpp"
#include <vector>
};
public:
- Composition();
+ explicit Composition(const world::Set<world::Resource> &);
~Composition();
Composition(const Composition &) = default;
bool Has(int res) const noexcept;
double Get(int res) const noexcept;
double Proportion(int res) const noexcept;
- double Compatibility(const world::Set<world::Resource> &, int res) const noexcept;
+ double StateProportion(int res) const noexcept;
+ double Compatibility(int res) const noexcept;
double TotalMass() const noexcept { return total_mass; }
+ double StateMass(world::Resource::State s) const noexcept { return state_mass[s]; }
public:
std::vector<Component>::size_type size() const noexcept { return components.size(); }
std::vector<Component>::const_iterator cend() noexcept { return components.cend(); }
private:
+ const world::Set<world::Resource> &resources;
std::vector<Component> components;
double total_mass;
+ double state_mass[4];
};
namespace blobs {
namespace creature {
-Composition::Composition()
-: components()
-, total_mass(0.0) {
+Composition::Composition(const world::Set<world::Resource> &resources)
+: resources(resources)
+, components()
+, total_mass(0.0)
+, state_mass{0.0} {
}
Composition::~Composition() {
if (c->resource == res) {
c->value += amount;
if (c->value <= 0.0) {
+ amount += c->value;
components.erase(c);
}
found = true;
components.emplace_back(res, amount);
}
std::sort(components.begin(), components.end(), CompositionCompare);
+ state_mass[resources[res].state] += amount;
total_mass += amount;
}
return Get(res) / TotalMass();
}
-double Composition::Compatibility(const world::Set<world::Resource> &resources, int res) const noexcept {
+double Composition::StateProportion(int res) const noexcept {
+ return Get(res) / StateMass(resources[res].state);
+}
+
+double Composition::Compatibility(int res) const noexcept {
if (Has(res)) {
- return Proportion(res);
+ return StateProportion(res);
}
double max_compat = -1.0;
double min_compat = 1.0;
for (const auto &c : components) {
- double prop = c.value / TotalMass();
+ double prop = c.value / StateMass(resources[res].state);
for (const auto &compat : resources[c.resource].compatibility) {
double value = compat.second * prop;
if (value > max_compat) {
, name()
, genome()
, properties()
-, composition()
+, composition(sim.Resources())
, base_color(1.0)
, highlight_color(0.0, 0.0, 0.0, 1.0)
, mass(1.0)
double nonsolid = 0.0;
double volume = 0.0;
for (const auto &c : composition) {
- volume += c.value / sim.Assets().data.resources[c.resource].density;
- if (sim.Assets().data.resources[c.resource].state != world::Resource::SOLID) {
+ volume += c.value / sim.Resources()[c.resource].density;
+ if (sim.Resources()[c.resource].state != world::Resource::SOLID) {
nonsolid += c.value;
}
}
void Creature::Ingest(int res, double amount) noexcept {
if (sim.Resources()[res].state == world::Resource::SOLID) {
// 30% of solids stays in body
- AddMass(res, amount * 0.3 * composition.Compatibility(sim.Resources(), res));
+ AddMass(res, amount * 0.3 * composition.Compatibility(res));
} else {
- // 10% of fluids stays in body
- AddMass(res, amount * 0.1 * composition.Compatibility(sim.Resources(), res));
+ // 5% of fluids stays in body
+ AddMass(res, amount * 0.05 * composition.Compatibility(res));
}
math::GaloisLFSR &random = sim.Assets().random;
if (random.UNorm() < AdaptChance()) {
IngestGoal::IngestGoal(Creature &c, Creature::Stat &stat)
: Goal(c)
, stat(stat)
-, accept()
+, accept(Assets().data.resources)
, locate_subtask(nullptr)
, ingesting(false)
, resource(-1)
}
if (ingesting) {
if (OnSuitableTile() && !GetSituation().Moving()) {
- GetCreature().Ingest(resource, yield * GetCreature().GetComposition().Compatibility(Assets().data.resources, resource) * dt);
+ GetCreature().Ingest(resource, yield * GetCreature().GetComposition().Compatibility(resource) * dt);
stat.Add(-1.0 * yield * dt);
if (stat.Empty()) {
SetComplete();
LocateResourceGoal::LocateResourceGoal(Creature &c)
: Goal(c)
-, accept()
+, accept(Assets().data.resources)
, found(false)
, target_pos(0.0)
, searching(false)