From: Daniel Karbach Date: Fri, 8 Dec 2017 19:57:07 +0000 (+0100) Subject: remember remember X-Git-Url: http://git.localhorst.tv/?p=blobs.git;a=commitdiff_plain;h=76c09039792065ca1c259fb4b681c84c29a9dbd8 remember remember --- diff --git a/src/creature/Creature.hpp b/src/creature/Creature.hpp index 0012d78..2c0b6b8 100644 --- a/src/creature/Creature.hpp +++ b/src/creature/Creature.hpp @@ -121,9 +121,13 @@ public: // stats with effects applied double Strength() const noexcept; + double StrengthFactor() const noexcept; double Stamina() const noexcept; + double StaminaFactor() const noexcept; double Dexerty() const noexcept; + double DexertyFactor() const noexcept; double Intelligence() const noexcept; + double IntelligenceFactor() const noexcept; double Lifetime() const noexcept; double Fertility() const noexcept; double Mutability() const noexcept; diff --git a/src/creature/LocateResourceGoal.hpp b/src/creature/LocateResourceGoal.hpp index c87f4f1..010b313 100644 --- a/src/creature/LocateResourceGoal.hpp +++ b/src/creature/LocateResourceGoal.hpp @@ -26,6 +26,8 @@ public: private: void LocateResource(); void SearchVicinity(); + void Remember(); + void RandomWalk(); bool NearTarget() const noexcept; private: diff --git a/src/creature/Memory.hpp b/src/creature/Memory.hpp index c58fd26..1d72c75 100644 --- a/src/creature/Memory.hpp +++ b/src/creature/Memory.hpp @@ -27,10 +27,16 @@ public: ~Memory(); public: - void Tick(double dt); - + /// remove all memories void Erase(); + /// try to remember where stuff was + /// when true, pos contains an approximation of the + /// location of the best fitting resource + bool RememberLocation(const Composition &, glm::dvec3 &pos) const noexcept; + + void Tick(double dt); + private: /// track time spent on a tile void TrackStay(const Location &, double t); diff --git a/src/creature/creature.cpp b/src/creature/creature.cpp index 7333fdc..deb5a10 100644 --- a/src/creature/creature.cpp +++ b/src/creature/creature.cpp @@ -294,18 +294,34 @@ double Creature::Strength() const noexcept { return properties.Strength() * ExhaustionFactor() * AgeFactor(0.25); } +double Creature::StrengthFactor() const noexcept { + return Strength() / (Strength() + 1.0); +} + double Creature::Stamina() const noexcept { return properties.Stamina() * ExhaustionFactor() * AgeFactor(0.25); } +double Creature::StaminaFactor() const noexcept { + return Stamina() / (Stamina() + 1.0); +} + double Creature::Dexerty() const noexcept { return properties.Dexerty() * ExhaustionFactor() * AgeFactor(0.25); } +double Creature::DexertyFactor() const noexcept { + return Dexerty() / (Dexerty() + 1.0); +} + double Creature::Intelligence() const noexcept { return properties.Intelligence() * FatigueFactor() * AgeFactor(0.25); } +double Creature::IntelligenceFactor() const noexcept { + return Intelligence() / (Intelligence() + 1.0); +} + double Creature::Lifetime() const noexcept { return properties.Lifetime(); } @@ -327,16 +343,16 @@ double Creature::OffspringMass() const noexcept { } double Creature::PerceptionRange() const noexcept { - return 3.0 * (Dexerty() / (Dexerty() + 1)) + Size(); + return 3.0 * DexertyFactor() + Size(); } double Creature::PerceptionOmniRange() const noexcept { - return 0.5 * (Dexerty() / (Dexerty() + 1)) + Size(); + return 0.5 * DexertyFactor() + 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)); + return 0.8 - DexertyFactor(); } bool Creature::PerceptionTest(const glm::dvec3 &p) const noexcept { @@ -773,11 +789,43 @@ void Memory::Erase() { known_types.clear(); } +bool Memory::RememberLocation(const Composition &accept, glm::dvec3 &pos) const noexcept { + double best_rating = -1.0; + for (const auto &k : known_types) { + const world::TileType &t = c.GetSimulation().TileTypes()[k.first]; + auto entry = t.FindBestResource(accept); + if (entry != t.resources.end()) { + double rating = entry->ubiquity / std::max(0.125, 0.25 * glm::length2(c.GetSituation().Position() - k.second.first_loc.position)); + if (rating > best_rating) { + best_rating = rating; + pos = k.second.first_loc.position; + } + rating = entry->ubiquity / std::max(0.125, 0.25 * glm::length2(c.GetSituation().Position() - k.second.last_loc.position)); + if (rating > best_rating) { + best_rating = rating; + pos = k.second.last_loc.position; + } + } + } + if (best_rating > 0.0) { + glm::dvec3 error( + c.GetSimulation().Assets().random.SNorm(), + c.GetSimulation().Assets().random.SNorm(), + c.GetSimulation().Assets().random.SNorm()); + pos += error * (2.0 * (1.0 - c.IntelligenceFactor())); + pos = glm::normalize(pos) * c.GetSituation().GetPlanet().Radius(); + return true; + } else { + return false; + } +} + void Memory::Tick(double dt) { Situation &s = c.GetSituation(); if (s.OnSurface()) { TrackStay({ &s.GetPlanet(), s.Position() }, dt); } + // TODO: forget } void Memory::TrackStay(const Location &l, double t) { diff --git a/src/creature/goal.cpp b/src/creature/goal.cpp index c3200a6..2d4347c 100644 --- a/src/creature/goal.cpp +++ b/src/creature/goal.cpp @@ -412,6 +412,12 @@ void LocateResourceGoal::LocateResource() { } else { // go find somewhere else SearchVicinity(); + if (!found) { + Remember(); + if (!found) { + RandomWalk(); + } + } } } else { // well, what now? @@ -441,7 +447,7 @@ void LocateResourceGoal::SearchVicinity() { // TODO: subtract minimum yield rating[y + search_radius][x + search_radius] = yield->ubiquity * accept.Get(yield->resource); // penalize distance - double dist = std::max(0.125, 0.25 * glm::length(tpos - pos)); + double dist = std::max(0.125, 0.25 * glm::length2(tpos - pos)); rating[y + search_radius][x + search_radius] /= dist; } } @@ -477,19 +483,41 @@ void LocateResourceGoal::SearchVicinity() { searching = false; target_pos = glm::normalize(pos + (double(best_pos.x) * step_x) + (double(best_pos.y) * step_y)) * planet.Radius(); GetSteering().GoTo(target_pos); - } else if (!searching) { - found = false; - searching = true; - target_pos = GetSituation().Position(); - target_pos += Random().SNorm() * step_x; - target_pos += Random().SNorm() * step_y; - // bias towards current heading - target_pos += GetSituation().Heading() * 1.5; - target_pos = glm::normalize(target_pos) * planet.Radius(); + } +} + +void LocateResourceGoal::Remember() { + glm::dvec3 pos(0.0); + if (GetCreature().GetMemory().RememberLocation(accept, pos)) { + found = true; + searching = false; + target_pos = pos; GetSteering().GoTo(target_pos); } } +void LocateResourceGoal::RandomWalk() { + if (searching) { + return; + } + + const world::Planet &planet = GetSituation().GetPlanet(); + const glm::dvec3 &pos = GetSituation().Position(); + const glm::dvec3 normal(planet.NormalAt(pos)); + const glm::dvec3 step_x(glm::normalize(glm::cross(normal, glm::dvec3(normal.z, normal.x, normal.y)))); + const glm::dvec3 step_y(glm::normalize(glm::cross(step_x, normal))); + + found = false; + searching = true; + target_pos = GetSituation().Position(); + target_pos += Random().SNorm() * step_x; + target_pos += Random().SNorm() * step_y; + // bias towards current heading + target_pos += GetSituation().Heading() * 1.5; + target_pos = glm::normalize(target_pos) * planet.Radius(); + GetSteering().GoTo(target_pos); +} + bool LocateResourceGoal::NearTarget() const noexcept { const Situation &s = GetSituation(); return s.OnSurface() && glm::length2(s.Position() - target_pos) < 0.5;