]> git.localhorst.tv Git - blobs.git/commitdiff
fix AI
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 28 Nov 2017 22:33:11 +0000 (23:33 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 28 Nov 2017 22:33:11 +0000 (23:33 +0100)
lol duh

src/creature/Creature.hpp
src/creature/Genome.hpp
src/creature/Situation.hpp
src/creature/Steering.hpp
src/creature/creature.cpp
src/creature/goal.cpp
src/creature/need.cpp
src/ui/ui.cpp

index f36a2db1f1172770855a9eebdfc6554202689b6f..d3cd86c462a7d8f22933ab2b8a0da41673a0ce25 100644 (file)
@@ -58,7 +58,7 @@ public:
        const Genome::Properties<double> &GetProperties() const noexcept { return properties; }
 
        const Genome::PropertySet<double> &CurProps() const noexcept { return properties.props[cur_prop]; }
-       const Genome::PropertySet<double> &NextProps() const noexcept { return properties.props[cur_prop + 1]; }
+       const Genome::PropertySet<double> &NextProps() const noexcept { return properties.props[std::min(5, cur_prop + 1)]; }
 
        void BaseColor(const glm::dvec3 &c) noexcept { base_color = c; }
        const glm::dvec3 &BaseColor() const noexcept { return base_color; }
@@ -68,13 +68,14 @@ public:
 
        void Mass(double m) noexcept { mass = m; size = std::cbrt(mass / density); }
        double Mass() const noexcept { return mass; }
-       void Grow(double amount) noexcept;
+       void Ingest(int res, double amount) noexcept;
 
        void Density(double d) noexcept { density = d; size = std::cbrt(mass / density); }
        double Density() const noexcept { return density; }
 
        double Size() const noexcept;
        double Age() const noexcept;
+       std::string AgeName() const;
        double AgeLerp(double from, double to) const noexcept;
        // change of giving birth per tick
        double Fertility() const noexcept;
index b14efc1a756396dd405906786eaffe7f1bc96fea..3361fdef2037d6f913a72ba12c098fe1ddc2e5de 100644 (file)
@@ -20,9 +20,13 @@ struct Genome {
 
        template<class T>
        struct PropertySet {
+               /// the age at which to transition to the next phase
                T age;
+               /// maximum body mass
                T mass;
+               /// fertility factor
                T fertility;
+               /// skin highlight pronounciation
                T highlight;
        };
        template<class T>
@@ -40,6 +44,20 @@ struct Genome {
                const PropertySet<T> &Elder() const noexcept { return props[4]; }
                PropertySet<T> &Death() noexcept { return props[5]; }
                const PropertySet<T> &Death() const noexcept { return props[5]; }
+
+               /// "typical" properties
+               /// every one of these should have at least one
+               /// negative impact to prevent super-beings evolving
+               /// power at the cost of higher solid intake
+               T strength;
+               /// more endurance at the cost of higher liquid intake
+               T stamina;
+               /// more speed at the cost of higher fatigue
+               T dexerty;
+               /// higher mental capacity at the cost of boredom
+               T intelligence;
+               /// how likely to mutate
+               T mutability;
        };
        Properties<math::Distribution> properties;
 
@@ -87,7 +105,12 @@ struct Genome {
                        Instantiate(p.props[2], rand),
                        Instantiate(p.props[3], rand),
                        Instantiate(p.props[4], rand),
-                       Instantiate(p.props[5], rand)
+                       Instantiate(p.props[5], rand),
+                       p.strength.FakeNormal(rand.SNorm()),
+                       p.stamina.FakeNormal(rand.SNorm()),
+                       p.dexerty.FakeNormal(rand.SNorm()),
+                       p.intelligence.FakeNormal(rand.SNorm()),
+                       p.mutability.FakeNormal(rand.SNorm())
                };
        }
 
index a12f4224c64ca9d9dcb5d8ab6cd4bc4ddb1f13ab..f29d9b08b96b0e5c07c4bb588e5a1f0cfa896928 100644 (file)
@@ -56,6 +56,7 @@ public:
        void SetState(const State &s) noexcept { state = s; }
        const State &GetState() const noexcept { return state; }
 
+       const glm::dvec3 &Velocity() const noexcept { return state.vel; }
        bool Moving() const noexcept { return glm::length2(state.vel) < 0.00000001; }
        void Move(const glm::dvec3 &dp) noexcept;
        void SetPlanetSurface(world::Planet &, int srf, const glm::dvec3 &pos) noexcept;
index 3ccf9e3d492dda6fa585849d0e393f7c81993ec9..cca757ee0b72763ec8b4f6558b8259d45ceedca2 100644 (file)
@@ -23,21 +23,24 @@ public:
 
 public:
        void Halt() noexcept;
+       void Pass(const glm::dvec3 &) noexcept;
        void GoTo(const glm::dvec3 &) noexcept;
 
        glm::dvec3 Acceleration(const Situation::State &) const noexcept;
 
 private:
        bool SumForce(glm::dvec3 &out, const glm::dvec3 &in) const noexcept;
+       glm::dvec3 TargetVelocity(const Situation::State &, const glm::dvec3 &) const noexcept;
 
 private:
-       glm::dvec3 seek_target;
+       glm::dvec3 target;
 
        double max_accel = 1.0;
        double max_speed = 1.0;
 
        bool halting;
        bool seeking;
+       bool arriving;
 
 };
 
index 92fa36795b2cea94e40f8c395c98e5cdb59c1e83..456e08102ebbb2d5cd45a7337a7f02ea508dd27f 100644 (file)
@@ -57,9 +57,20 @@ glm::dvec4 Creature::HighlightColor() const noexcept {
        return glm::dvec4(highlight_color, AgeLerp(CurProps().highlight, NextProps().highlight));
 }
 
-void Creature::Grow(double amount) noexcept {
-       const double max_mass = AgeLerp(CurProps().mass, NextProps().mass);
-       Mass(std::min(max_mass, mass + amount));
+void Creature::Ingest(int res, double amount) noexcept {
+       const Genome::Composition *cmp = nullptr;
+       for (const auto &c : genome.composition) {
+               if (c.resource == res) {
+                       cmp = &c;
+                       break;
+               }
+       }
+       if (cmp) {
+               const double max_mass = AgeLerp(CurProps().mass, NextProps().mass);
+               Mass(std::min(max_mass, mass + amount));
+       } else {
+               // foreign material. poisonous?
+       }
 }
 
 void Creature::Hurt(double dt) noexcept {
@@ -89,6 +100,25 @@ double Creature::Age() const noexcept {
        return sim.Time() - birth;
 }
 
+std::string Creature::AgeName() const {
+       switch (cur_prop) {
+               case 0:
+                       return "Newborn";
+               case 1:
+                       return "Child";
+               case 2:
+                       return "Youth";
+               case 3:
+                       return "Adult";
+               case 4:
+                       return "Elder";
+               case 5:
+                       return "Dead";
+               default:
+                       return "Unknown";
+       }
+}
+
 double Creature::AgeLerp(double from, double to) const noexcept {
        return glm::mix(from, to, glm::smoothstep(CurProps().age, NextProps().age, Age()));
 }
@@ -112,13 +142,12 @@ bool GoalCompare(const std::unique_ptr<Goal> &a, const std::unique_ptr<Goal> &b)
 }
 
 void Creature::Tick(double dt) {
-       if (cur_prop < 5 && Age() > properties.props[cur_prop + 1].age) {
-               if (cur_prop == 4) {
+       if (cur_prop < 5 && Age() > NextProps().age) {
+               ++cur_prop;
+               if (cur_prop == 5) {
                        std::cout << "[" << int(sim.Time()) << "s] "
                                << name << " died of old age" << std::endl;
                        Die();
-               } else {
-                       ++cur_prop;
                }
        }
 
@@ -339,6 +368,12 @@ void Spawn(Creature &c, world::Planet &p) {
        genome.properties.Death().fertility = { 0.0, 0.0 };
        genome.properties.Death().highlight = { 0.5, 0.1 };
 
+       genome.properties.strength = { 1.0, 0.1 };
+       genome.properties.stamina = { 1.0, 0.1 };
+       genome.properties.dexerty = { 1.0, 0.1 };
+       genome.properties.intelligence = { 1.0, 0.1 };
+       genome.properties.mutability = { 1.0, 0.1 };
+
        glm::dvec3 color_avg(0.0);
        double color_divisor = 0.0;
 
@@ -397,6 +432,7 @@ void Genome::Configure(Creature &c) const {
        double mass = 0.0;
        double volume = 0.0;
        for (const auto &comp : composition) {
+               const world::Resource &resource = c.GetSimulation().Resources()[comp.resource];
                double comp_mass = comp.mass.FakeNormal(random.SNorm());
                double intake = comp.intake.FakeNormal(random.SNorm());
                double penalty = comp.penalty.FakeNormal(random.SNorm());
@@ -405,10 +441,12 @@ void Genome::Configure(Creature &c) const {
                volume += comp_mass / c.GetSimulation().Resources()[comp.resource].density;
 
                std::unique_ptr<Need> need;
-               if (c.GetSimulation().Resources()[comp.resource].state == world::Resource::SOLID) {
+               if (resource.state == world::Resource::SOLID) {
+                       intake *= std::atan(c.GetProperties().strength);
                        need.reset(new IngestNeed(comp.resource, intake, penalty));
                        need->gain = intake * 0.05;
-               } else if (c.GetSimulation().Resources()[comp.resource].state == world::Resource::LIQUID) {
+               } else if (resource.state == world::Resource::LIQUID) {
+                       intake *= std::atan(c.GetProperties().stamina);
                        need.reset(new IngestNeed(comp.resource, intake, penalty));
                        need->gain = intake * 0.1;
                } else {
@@ -416,7 +454,6 @@ void Genome::Configure(Creature &c) const {
                        need->gain = intake * 0.5;
                }
                need->name = c.GetSimulation().Resources()[comp.resource].label;
-               need->growth = comp.growth.FakeNormal(random.SNorm());
                need->inconvenient = 0.5;
                need->critical = 0.95;
                c.AddNeed(std::move(need));
@@ -437,8 +474,8 @@ void Genome::Configure(Creature &c) const {
 
        c.Mass(c.GetProperties().props[0].mass);
        c.Density(mass / volume);
-       c.GetSteering().MaxAcceleration(1.4);
-       c.GetSteering().MaxSpeed(4.4);
+       c.GetSteering().MaxAcceleration(1.4 * std::atan(c.GetProperties().strength));
+       c.GetSteering().MaxSpeed(4.4 * std::atan(c.GetProperties().dexerty));
        c.AddGoal(std::unique_ptr<Goal>(new IdleGoal(c)));
 }
 
@@ -576,11 +613,12 @@ void Situation::SetPlanetSurface(world::Planet &p, int srf, const glm::dvec3 &po
 
 
 Steering::Steering()
-: seek_target(0.0)
+: target(0.0)
 , max_accel(1.0)
 , max_speed(1.0)
 , halting(false)
-, seeking(false) {
+, seeking(false)
+, arriving(false) {
 }
 
 Steering::~Steering() {
@@ -589,12 +627,21 @@ Steering::~Steering() {
 void Steering::Halt() noexcept {
        halting = true;
        seeking = false;
+       arriving = false;
 }
 
-void Steering::GoTo(const glm::dvec3 &t) noexcept {
-       seek_target = t;
+void Steering::Pass(const glm::dvec3 &t) noexcept {
+       target = t;
        halting = false;
        seeking = true;
+       arriving = false;
+}
+
+void Steering::GoTo(const glm::dvec3 &t) noexcept {
+       target = t;
+       halting = false;
+       seeking = false;
+       arriving = true;
 }
 
 glm::dvec3 Steering::Acceleration(const Situation::State &s) const noexcept {
@@ -603,9 +650,16 @@ glm::dvec3 Steering::Acceleration(const Situation::State &s) const noexcept {
                SumForce(acc, s.vel * -max_accel);
        }
        if (seeking) {
-               glm::dvec3 diff = seek_target - s.pos;
+               glm::dvec3 diff = target - s.pos;
                if (!allzero(diff)) {
-                       SumForce(acc, ((normalize(diff) * max_speed) - s.vel) * max_accel);
+                       SumForce(acc, TargetVelocity(s, (normalize(diff) * max_speed)));
+               }
+       }
+       if (arriving) {
+               glm::dvec3 diff = target - s.pos;
+               double dist = length(diff);
+               if (!allzero(diff) && dist > std::numeric_limits<double>::epsilon()) {
+                       SumForce(acc, TargetVelocity(s, diff * std::min(dist * max_accel, max_speed) / dist));
                }
        }
        return acc;
@@ -632,5 +686,9 @@ bool Steering::SumForce(glm::dvec3 &out, const glm::dvec3 &in) const noexcept {
        }
 }
 
+glm::dvec3 Steering::TargetVelocity(const Situation::State &s, const glm::dvec3 &vel) const noexcept {
+       return (vel - s.vel) * max_accel;
+}
+
 }
 }
index ee51a919ba11a71ff7081262b4ebd3f9076c5d10..9c45a344f22a1fe9b1f55498d8e7caa5d00ec09b 100644 (file)
@@ -130,8 +130,7 @@ void LocateResourceGoal::Action() {
                } else {
                        double dist = glm::length2(GetSituation().Position() - target_pos);
                        if (dist < 0.0001) {
-                               GetSteering().Halt();
-                               searching = false;
+                               LocateResource();
                        } else {
                                GetSteering().GoTo(target_pos);
                        }
@@ -212,6 +211,8 @@ void LocateResourceGoal::SearchVicinity() {
                target_pos = GetSituation().Position();
                target_pos[(srf + 0) % 3] += Assets().random.SNorm();
                target_pos[(srf + 1) % 3] += Assets().random.SNorm();
+               // bias towards current direction
+               target_pos += glm::normalize(GetSituation().Velocity()) * 0.5;
                GetSteering().GoTo(target_pos);
        }
 }
index 1b832b7e17483df2ed44f2ab85891006cc54e834..576655a97185ec8740cde7fe6385d1128485509e 100644 (file)
@@ -51,7 +51,7 @@ void IngestNeed::ApplyEffect(Creature &c, double dt) {
                                        found = true;
                                        // TODO: check if not busy with something else
                                        double amount = std::min(yield.ubiquity, speed) * dt;
-                                       c.Grow(amount * growth * dt);
+                                       c.Ingest(resource, amount * growth * dt);
                                        Decrease(amount);
                                        if (value == 0.0) {
                                                ingesting = false;
index c53426a65c8c119ad8204e3fa7fa78de02f330cd..e62894db3cdeef62af513a5d3e5aa4da10b9f5e5 100644 (file)
@@ -43,7 +43,7 @@ CreaturePanel::CreaturePanel(const app::Assets &assets)
                ->Spacing(10.0f)
                ->Direction(Panel::HORIZONTAL);
 
-       age->Text("0000s");
+       age->Text("0000s (Newborn)");
        Label *age_label = new Label(assets.fonts.medium);
        age_label->Text("Age");
        Panel *age_panel = new Panel;
@@ -152,7 +152,7 @@ void CreaturePanel::Hide() noexcept {
 void CreaturePanel::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
        if (!c) return;
 
-       age->Text(std::to_string(int(c->Age())) + "s");
+       age->Text(std::to_string(int(c->Age())) + "s (" + c->AgeName() + ")");
        {
                std::stringstream ss;
                ss << std::fixed << std::setprecision(3) << c->Mass() << "kg";