X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fcreature%2Fcreature.cpp;h=7333fdc42978693728e2d2bf599c9e3c159669b1;hb=0e061ce526fe46dd3e894223e5d646eb2e30f826;hp=d7a9724fbe62474884cf9538165efbac1df73b81;hpb=215c77b9d61ed635176edb86e54c6e87a1315dcf;p=blobs.git diff --git a/src/creature/creature.cpp b/src/creature/creature.cpp index d7a9724..7333fdc 100644 --- a/src/creature/creature.cpp +++ b/src/creature/creature.cpp @@ -193,7 +193,7 @@ void Creature::Ingest(int res, double amount) noexcept { } void Creature::DoWork(double amount) noexcept { - stats.Exhaustion().Add(amount / Stamina()); + stats.Exhaustion().Add(amount / (Stamina() + 1.0)); // burn resources proportional to composition // factor = 1/total * 1/efficiency * amount * -1 double factor = -amount / (composition.TotalMass() * EnergyEfficiency()); @@ -204,6 +204,8 @@ void Creature::DoWork(double amount) noexcept { double value = cmp.value * factor * sim.Resources()[cmp.resource].inverse_energy; AddMass(cmp.resource, value); } + // doing work improves strength a little + properties.Strength() += amount * 0.0001; } void Creature::Hurt(double amount) noexcept { @@ -340,10 +342,10 @@ double Creature::PerceptionField() const noexcept { 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; + if (glm::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(); + if (glm::length2(diff) > range * range) return false; + return glm::dot(glm::normalize(diff), situation.Heading()) > PerceptionField(); } double Creature::OffspringChance() const noexcept { @@ -360,6 +362,9 @@ double Creature::AdaptChance() const noexcept { void Creature::AddGoal(std::unique_ptr &&g) { g->Enable(); + if (goals.empty()) { + g->SetForeground(); + } goals.emplace_back(std::move(g)); } @@ -392,21 +397,21 @@ void Creature::TickState(double dt) { state.pos += f.vel * dt; state.vel += f.acc * dt; situation.EnforceConstraints(state); - if (length2(state.vel) > 0.000001) { - glm::dvec3 nvel(normalize(state.vel)); - double ang = angle(nvel, state.dir); + if (glm::length2(state.vel) > 0.000001) { + glm::dvec3 nvel(glm::normalize(state.vel)); + double ang = glm::angle(nvel, state.dir); double turn_rate = PI * 0.75 * dt; if (ang < turn_rate) { - state.dir = normalize(state.vel); + state.dir = glm::normalize(state.vel); } else if (std::abs(ang - PI) < 0.001) { - state.dir = rotate(state.dir, turn_rate, world::Planet::SurfaceNormal(situation.Surface())); + state.dir = glm::rotate(state.dir, turn_rate, situation.GetPlanet().NormalAt(state.pos)); } else { - state.dir = rotate(state.dir, turn_rate, normalize(cross(state.dir, nvel))); + state.dir = glm::rotate(state.dir, turn_rate, glm::normalize(glm::cross(state.dir, nvel))); } } situation.SetState(state); // work is force times distance - DoWork(length(f.acc) * Mass() * length(f.vel) * dt); + DoWork(glm::length(f.acc) * Mass() * glm::length(f.vel) * dt); } Situation::Derivative Creature::Step(const Situation::Derivative &ds, double dt) const noexcept { @@ -415,8 +420,8 @@ Situation::Derivative Creature::Step(const Situation::Derivative &ds, double dt) s.vel += ds.acc * dt; glm::dvec3 force(steering.Force(s)); // gravity = antinormal * mass * Gm / r² - double elevation = s.pos[(situation.Surface() + 2) % 3]; - glm::dvec3 normal(world::Planet::SurfaceNormal(situation.Surface())); + double elevation = situation.GetPlanet().DistanceAt(s.pos); + glm::dvec3 normal(situation.GetPlanet().NormalAt(s.pos)); force += glm::dvec3( -normal * Mass() * situation.GetPlanet().GravitationalParameter() @@ -424,10 +429,10 @@ Situation::Derivative Creature::Step(const Situation::Derivative &ds, double dt) // if net force is applied and in contact with surface if (!allzero(force) && std::abs(std::abs(elevation) - situation.GetPlanet().Radius()) < 0.001) { // apply friction = -|normal force| * tangential force * coefficient - glm::dvec3 fn(normal * dot(force, normal)); + glm::dvec3 fn(normal * glm::dot(force, normal)); glm::dvec3 ft(force - fn); double u = 0.4; - glm::dvec3 friction(-length(fn) * ft * u); + glm::dvec3 friction(-glm::length(fn) * ft * u); force += friction; } return { @@ -470,10 +475,16 @@ void Creature::TickBrain(double dt) { for (auto &goal : goals) { goal->Tick(dt); } + Goal *top = &*goals.front(); // if active goal can be interrupted, check priorities if (goals.size() > 1 && goals[0]->Interruptible()) { std::sort(goals.begin(), goals.end(), GoalCompare); } + if (&*goals.front() != top) { + top->SetBackground(); + goals.front()->SetForeground(); + top = &*goals.front(); + } goals[0]->Action(); for (auto goal = goals.begin(); goal != goals.end();) { if ((*goal)->Complete()) { @@ -482,6 +493,9 @@ void Creature::TickBrain(double dt) { ++goal; } } + if (&*goals.front() != top) { + goals.front()->SetForeground(); + } } math::AABB Creature::CollisionBox() const noexcept { @@ -491,10 +505,17 @@ math::AABB Creature::CollisionBox() const noexcept { glm::dmat4 Creature::CollisionTransform() const noexcept { const double half_size = size * 0.5; const glm::dvec3 &pos = situation.Position(); - const glm::dmat3 srf(world::Planet::SurfaceOrientation(situation.Surface())); - return glm::translate(glm::dvec3(pos.x, pos.y, pos.z + half_size)) - * glm::rotate(glm::orientedAngle(-srf[2], situation.Heading(), srf[1]), srf[1]) - * glm::dmat4(srf); + glm::dmat3 orient; + orient[1] = situation.GetPlanet().NormalAt(pos); + orient[2] = situation.Heading(); + if (std::abs(glm::dot(orient[1], orient[2])) > 0.999) { + orient[2] = glm::dvec3(orient[1].z, orient[1].x, orient[1].y); + } + orient[0] = glm::normalize(glm::cross(orient[1], orient[2])); + orient[2] = glm::normalize(glm::cross(orient[0], orient[1])); + return glm::translate(glm::dvec3(pos.x, pos.y, pos.z)) + * glm::dmat4(orient) + * glm::translate(glm::dvec3(0.0, half_size, 0.0)); } glm::dmat4 Creature::LocalTransform() noexcept { @@ -599,8 +620,8 @@ void Creature::Draw(graphics::Viewport &viewport) { void Spawn(Creature &c, world::Planet &p) { p.AddCreature(&c); - c.GetSituation().SetPlanetSurface(p, 0, p.TileCenter(0, p.SideLength() / 2, p.SideLength() / 2)); - c.GetSituation().Heading(-world::Planet::SurfaceOrientation(0)[2]); + c.GetSituation().SetPlanetSurface(p, glm::dvec3(0.0, 0.0, p.Radius())); + c.GetSituation().Heading(glm::dvec3(1.0, 0.0, 0.0)); // probe surrounding area for common resources int start = p.SideLength() / 2 - 2; @@ -718,7 +739,7 @@ void Split(Creature &c) { s.GetPlanet().AddCreature(a); // TODO: duplicate situation somehow a->GetSituation().SetPlanetSurface( - s.GetPlanet(), s.Surface(), + s.GetPlanet(), s.Position() + glm::dvec3(0.0, 0.55 * a->Size(), 0.0)); a->BuildVAO(); c.GetSimulation().Log() << a->Name() << " was born" << std::endl; @@ -732,7 +753,7 @@ void Split(Creature &c) { } s.GetPlanet().AddCreature(b); b->GetSituation().SetPlanetSurface( - s.GetPlanet(), s.Surface(), + s.GetPlanet(), s.Position() - glm::dvec3(0.0, 0.55 * b->Size(), 0.0)); b->BuildVAO(); c.GetSimulation().Log() << b->Name() << " was born" << std::endl; @@ -754,13 +775,13 @@ void Memory::Erase() { void Memory::Tick(double dt) { Situation &s = c.GetSituation(); - if (s.OnTile()) { - TrackStay({ &s.GetPlanet(), s.Surface(), s.SurfacePosition() }, dt); + if (s.OnSurface()) { + TrackStay({ &s.GetPlanet(), s.Position() }, dt); } } void Memory::TrackStay(const Location &l, double t) { - const world::TileType &type = l.planet->TypeAt(l.surface, l.coords.x, l.coords.y); + const world::TileType &type = l.planet->TileTypeAt(l.position); auto entry = known_types.find(type.id); if (entry != known_types.end()) { if (c.GetSimulation().Time() - entry->second.last_been > c.GetProperties().Lifetime() * 0.1) { @@ -808,7 +829,6 @@ std::string NameGenerator::Sequential() { Situation::Situation() : planet(nullptr) , state(glm::dvec3(0.0), glm::dvec3(0.0)) -, surface(0) , type(LOST) { } @@ -823,25 +843,12 @@ bool Situation::OnSurface() const noexcept { return type == PLANET_SURFACE; } -bool Situation::OnTile() const noexcept { - if (type != PLANET_SURFACE) return false; - glm::ivec2 t(planet->SurfacePosition(surface, state.pos)); - return t.x >= 0 && t.x < planet->SideLength() - && t.y >= 0 && t.y < planet->SideLength(); -} - -glm::ivec2 Situation::SurfacePosition() const noexcept { - return planet->SurfacePosition(surface, state.pos); -} - world::Tile &Situation::GetTile() const noexcept { - glm::ivec2 t(planet->SurfacePosition(surface, state.pos)); - return planet->TileAt(surface, t.x, t.y); + return planet->TileAt(state.pos); } const world::TileType &Situation::GetTileType() const noexcept { - glm::ivec2 t(planet->SurfacePosition(surface, state.pos)); - return planet->TypeAt(surface, t.x, t.y); + return planet->TileTypeAt(state.pos); } void Situation::Move(const glm::dvec3 &dp) noexcept { @@ -856,24 +863,16 @@ void Situation::Accelerate(const glm::dvec3 &dv) noexcept { void Situation::EnforceConstraints(State &s) noexcept { if (OnSurface()) { - if (Surface() < 3) { - if (s.pos[(Surface() + 2) % 3] < GetPlanet().Radius()) { - s.pos[(Surface() + 2) % 3] = GetPlanet().Radius(); - s.vel[(Surface() + 2) % 3] = std::max(0.0, s.vel[(Surface() + 2) % 3]); - } - } else { - if (s.pos[(Surface() + 2) % 3] > -GetPlanet().Radius()) { - s.pos[(Surface() + 2) % 3] = -GetPlanet().Radius(); - s.vel[(Surface() + 2) % 3] = std::min(0.0, s.vel[(Surface() + 2) % 3]); - } + double r = GetPlanet().Radius(); + if (glm::length2(s.pos) < r * r) { + s.pos = glm::normalize(s.pos) * r; } } } -void Situation::SetPlanetSurface(world::Planet &p, int srf, const glm::dvec3 &pos) noexcept { +void Situation::SetPlanetSurface(world::Planet &p, const glm::dvec3 &pos) noexcept { type = PLANET_SURFACE; planet = &p; - surface = srf; state.pos = pos; EnforceConstraints(state); } @@ -948,10 +947,10 @@ glm::dvec3 Steering::Force(const Situation::State &s) const noexcept { for (auto &other : s.GetPlanet().Creatures()) { if (&*other == &c) continue; glm::dvec3 diff = s.Position() - other->GetSituation().Position(); - if (length2(diff) > max_look * max_look) continue; + if (glm::length2(diff) > max_look * max_look) continue; if (!c.PerceptionTest(other->GetSituation().Position())) continue; - double sep = glm::clamp(length(diff) - other->Size() * 0.707 - c.Size() * 0.707, 0.0, min_dist); - repulse += normalize(diff) * (1.0 - sep / min_dist) * force; + double sep = glm::clamp(glm::length(diff) - other->Size() * 0.707 - c.Size() * 0.707, 0.0, min_dist); + repulse += glm::normalize(diff) * (1.0 - sep / min_dist) * force; } result += repulse; } @@ -962,18 +961,18 @@ glm::dvec3 Steering::Force(const Situation::State &s) const noexcept { if (seeking) { glm::dvec3 diff = target - s.pos; if (!allzero(diff)) { - result += TargetVelocity(s, (normalize(diff) * speed), force); + result += TargetVelocity(s, (glm::normalize(diff) * speed), force); } } if (arriving) { glm::dvec3 diff = target - s.pos; - double dist = length(diff); + double dist = glm::length(diff); if (!allzero(diff) && dist > std::numeric_limits::epsilon()) { result += TargetVelocity(s, diff * std::min(dist * force, speed) / dist, force); } } - if (length2(result) > max_force * max_force) { - result = normalize(result) * max_force; + if (glm::length2(result) > max_force * max_force) { + result = glm::normalize(result) * max_force; } return result; }