+ known_creatures.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 * (4.0 * (1.0 - c.IntelligenceFactor()));
+ pos = glm::normalize(pos) * c.GetSituation().GetPlanet().Radius();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void Memory::TrackCollision(Creature &other) {
+ // TODO: find out whose fault it was
+ // TODO: source values from personality
+ Profile &p = known_creatures[&other];
+ p.annoyance += 0.1;
+ const double annoy_fact = p.annoyance / (p.annoyance + 1.0);
+ if (c.GetSimulation().Assets().random.UNorm() > annoy_fact * 0.1 * (1.0 - c.GetStats().Damage().value)) {
+ AttackGoal *g = new AttackGoal(c, other);
+ g->SetDamageTarget(annoy_fact);
+ g->Urgency(annoy_fact);
+ c.AddGoal(std::unique_ptr<Goal>(g));
+ p.annoyance *= 0.5;
+ }