X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fcreature%2Fcreature.cpp;h=39b96b22cafda71e9cfdae849e5cb50234319ffa;hb=a51e14dee931d657e2517fda4adf86698283e57c;hp=de82f86ad9a7db52924106735450f49ee8033a8c;hpb=d364d8a9203138be1c569cdc31144f51883ec79f;p=blobs.git diff --git a/src/creature/creature.cpp b/src/creature/creature.cpp index de82f86..39b96b2 100644 --- a/src/creature/creature.cpp +++ b/src/creature/creature.cpp @@ -92,7 +92,7 @@ Creature::Creature(world::Simulation &sim) , mass(1.0) , size(1.0) , birth(sim.Time()) -, death(0.0) +, death(-1.0) , on_death() , removable(false) , parents() @@ -209,36 +209,42 @@ void Creature::DoWork(double amount) noexcept { void Creature::Hurt(double amount) noexcept { stats.Damage().Add(amount); if (stats.Damage().Full()) { - std::cout << "[" << ui::TimeString(sim.Time()) << "] " << name << " "; + std::ostream &log = sim.Log() << name << " "; if (stats.Exhaustion().Full()) { - std::cout << "died of exhaustion"; + log << "died of exhaustion"; } else if (stats.Breath().Full()) { - std::cout << "suffocated"; + log << "suffocated"; } else if (stats.Thirst().Full()) { - std::cout << "died of thirst"; + log << "died of thirst"; } else if (stats.Hunger().Full()) { - std::cout << "starved to death"; + log << "starved to death"; } else { - std::cout << "succumed to wounds"; + log << "succumed to wounds"; } - std::cout << " at an age of " << ui::TimeString(Age()) + log << " at an age of " << ui::TimeString(Age()) << " (" << ui::PercentageString(Age() / properties.Lifetime()) - << "% of life expectancy of " << ui::TimeString(properties.Lifetime()) + << " of life expectancy of " << ui::TimeString(properties.Lifetime()) << ")" << std::endl; Die(); } } void Creature::Die() noexcept { + if (Dead()) return; + sim.SetDead(this); death = sim.Time(); - steering.Halt(); + steering.Off(); if (on_death) { on_death(*this); } Remove(); } +bool Creature::Dead() const noexcept { + return death > birth; +} + void Creature::Remove() noexcept { removable = true; } @@ -315,6 +321,28 @@ double Creature::OffspringMass() const noexcept { return properties.OffspringMass(); } +double Creature::PerceptionRange() const noexcept { + return 3.0 * (Dexerty() / (Dexerty() + 1)) + Size(); +} + +double Creature::PerceptionOmniRange() const noexcept { + return 0.5 * (Dexerty() / (Dexerty() + 1)) + Size(); +} + +double Creature::PerceptionField() const noexcept { + // this is the cosine of half the angle, so 1.0 is none, -1.0 is perfect + return 0.8 - (Dexerty() / (Dexerty() + 1)); +} + +bool Creature::PerceptionTest(const glm::dvec3 &p) const noexcept { + const glm::dvec3 diff(p - situation.Position()); + double omni_range = PerceptionOmniRange(); + if (length2(diff) < omni_range * omni_range) return true; + double range = PerceptionRange(); + if (length2(diff) > range * range) return false; + return dot(normalize(diff), situation.Heading()) > PerceptionField(); +} + double Creature::OffspringChance() const noexcept { return AgeFactor(0.25) * properties.Fertility() * (1.0 / 3600.0); } @@ -409,7 +437,6 @@ void Creature::TickStats(double dt) { for (auto &s : stats.stat) { s.Add(s.gain * dt); } - stats.Breath().Add(stats.Breath().gain * stats.Exhaustion().value * dt); // TODO: damage values depending on properties if (stats.Breath().Full()) { constexpr double dps = 1.0 / 4.0; @@ -691,8 +718,7 @@ void Split(Creature &c) { s.GetPlanet(), s.Surface(), s.Position() + glm::dvec3(0.0, 0.55 * a->Size(), 0.0)); a->BuildVAO(); - std::cout << "[" << ui::TimeString(c.GetSimulation().Time()) << "] " - << a->Name() << " was born" << std::endl; + c.GetSimulation().Log() << a->Name() << " was born" << std::endl; Creature *b = new Creature(c.GetSimulation()); b->AddParent(c); @@ -706,8 +732,7 @@ void Split(Creature &c) { s.GetPlanet(), s.Surface(), s.Position() - glm::dvec3(0.0, 0.55 * b->Size(), 0.0)); b->BuildVAO(); - std::cout << "[" << ui::TimeString(c.GetSimulation().Time()) << "] " - << b->Name() << " was born" << std::endl; + c.GetSimulation().Log() << b->Name() << " was born" << std::endl; c.Die(); } @@ -868,6 +893,13 @@ Steering::Steering(const Creature &c) Steering::~Steering() { } +void Steering::Off() noexcept { + separating = false; + halting = false; + seeking = false; + arriving = false; +} + void Steering::Separate(double min_distance, double max_lookaround) noexcept { separating = true; min_dist = min_distance; @@ -914,52 +946,35 @@ glm::dvec3 Steering::Force(const Situation::State &s) const noexcept { if (&*other == &c) continue; glm::dvec3 diff = s.Position() - other->GetSituation().Position(); if (length2(diff) > max_look * max_look) continue; + if (!c.PerceptionTest(other->GetSituation().Position())) continue; double sep = length(diff) - other->Size() * 0.707 - c.Size() * 0.707; if (sep < min_dist) { repulse += normalize(diff) * (1.0 - sep / min_dist); } } - SumForce(result, repulse, force); + result += repulse; } if (halting) { // break twice as hard - SumForce(result, s.vel * force * -2.0, force); + result += -2.0 * s.vel * force; } if (seeking) { glm::dvec3 diff = target - s.pos; if (!allzero(diff)) { - SumForce(result, TargetVelocity(s, (normalize(diff) * speed), force), force); + result += TargetVelocity(s, (normalize(diff) * speed), force); } } if (arriving) { glm::dvec3 diff = target - s.pos; double dist = length(diff); if (!allzero(diff) && dist > std::numeric_limits::epsilon()) { - SumForce(result, TargetVelocity(s, diff * std::min(dist * force, speed) / dist, force), force); + result += TargetVelocity(s, diff * std::min(dist * force, speed) / dist, force); } } - return result; -} - -bool Steering::SumForce(glm::dvec3 &out, const glm::dvec3 &in, double max) const noexcept { - if (allzero(in) || anynan(in)) { - return false; - } - double cur = allzero(out) ? 0.0 : length(out); - double rem = max - cur; - if (rem < 0.0) { - return true; - } - double add = length(in); - if (add > rem) { - // this method is off if in and out are in different - // directions, but gives okayish results - out += in * (1.0 / add); - return true; - } else { - out += in; - return false; + if (length2(result) > max_force * max_force) { + result = normalize(result) * max_force; } + return result; } glm::dvec3 Steering::TargetVelocity(const Situation::State &s, const glm::dvec3 &vel, double acc) const noexcept {