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 0.0;
}
+double Composition::Proportion(int res) const noexcept {
+ return Get(res) / TotalMass();
+}
+
+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 StateProportion(res);
+ }
+ double max_compat = -1.0;
+ double min_compat = 1.0;
+ for (const auto &c : components) {
+ 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) {
+ 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)
, 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 {
- // 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(res));
} else {
- // 10% of fluids stays in body
- AddMass(res, amount * 0.05);
+ // 5% of fluids stays in body
+ AddMass(res, amount * 0.05 * composition.Compatibility(res));
}
math::GaloisLFSR &random = sim.Assets().random;
if (random.UNorm() < AdaptChance()) {
}
double Creature::Age() const noexcept {
- return sim.Time() - birth;
+ return Dead() ? death - birth : sim.Time() - birth;
}
double Creature::AgeFactor(double peak) const noexcept {
result += repulse;
}
if (halting) {
- // break twice as hard
- result += -2.0 * s.vel * force;
+ // brake hard
+ result += -5.0 * s.vel * force;
}
if (seeking) {
glm::dvec3 diff = target - s.pos;