]> git.localhorst.tv Git - blobs.git/commitdiff
color mutation
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 3 Dec 2017 23:27:11 +0000 (00:27 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 3 Dec 2017 23:27:11 +0000 (00:27 +0100)
I don't see it

src/creature/Creature.hpp
src/creature/Genome.hpp
src/creature/creature.cpp
src/creature/goal.cpp
src/math/GaloisLFSR.hpp
src/ui/CreaturePanel.hpp
src/ui/ui.cpp

index 4d16f99bd35857689b5f1e09b8dcb9deffcd854a..498ebeac8d7665ccc68986b4376812d62ee6935c 100644 (file)
@@ -127,12 +127,15 @@ public:
        double Lifetime() const noexcept;
        double Fertility() const noexcept;
        double Mutability() const noexcept;
+       double Adaptability() const noexcept;
        double OffspringMass() const noexcept;
 
        /// chance of giving birth per tick
        double OffspringChance() const noexcept;
-       /// chance of random genetic mutation per tick
+       /// chance of arbitrary genetic mutation per tick
        double MutateChance() const noexcept;
+       /// chance of environmental genetic mutation per tick
+       double AdaptChance() const noexcept;
 
        void Hurt(double d) noexcept;
        void Die() noexcept;
index 75ca79c70188c439c4683b3a238e8271663d9196..1fc5c2a5f4871f22eb8f00dab6c2ad81c1c9e590 100644 (file)
@@ -22,7 +22,7 @@ struct Genome {
        struct Properties {
                /// every one of these should have at least one
                /// negative impact to prevent super-beings evolving
-               T props[8];
+               T props[9];
                /// power at the cost of higher solid intake
                T &Strength() noexcept { return props[0]; }
                const T &Strength() const noexcept { return props[0]; }
@@ -44,9 +44,12 @@ struct Genome {
                /// how likely to mutate
                T &Mutability() noexcept { return props[6]; }
                const T &Mutability() const noexcept { return props[6]; }
+               /// how likely to adapt to new environments
+               T &Adaptability() noexcept { return props[7]; }
+               const T &Adaptability() const noexcept { return props[7]; }
                /// mass of offspring
-               T &OffspringMass() noexcept { return props[7]; }
-               const T &OffspringMass() const noexcept { return props[7]; }
+               T &OffspringMass() noexcept { return props[8]; }
+               const T &OffspringMass() const noexcept { return props[8]; }
        };
        Properties<math::Distribution> properties;
 
@@ -54,6 +57,10 @@ struct Genome {
        math::Distribution base_saturation;
        math::Distribution base_lightness;
 
+       math::Distribution highlight_hue;
+       math::Distribution highlight_saturation;
+       math::Distribution highlight_lightness;
+
        void Configure(Creature &) const;
 
        static Properties<double> Instantiate(
@@ -66,9 +73,10 @@ struct Genome {
                        p.props[2].FakeNormal(rand.SNorm()),
                        p.props[3].FakeNormal(rand.SNorm()),
                        p.props[4].FakeNormal(rand.SNorm()),
-                       p.props[5].FakeNormal(rand.SNorm()),
-                       p.props[6].FakeNormal(rand.SNorm()),
-                       p.props[7].FakeNormal(rand.SNorm())
+                       glm::clamp(p.props[5].FakeNormal(rand.SNorm()), 0.0, 1.0),
+                       glm::clamp(p.props[6].FakeNormal(rand.SNorm()), 0.0, 1.0),
+                       glm::clamp(p.props[7].FakeNormal(rand.SNorm()), 0.0, 1.0),
+                       p.props[8].FakeNormal(rand.SNorm())
                };
        }
 
index 9ef8dd9d3148f691160f5effaf5e80974133d68f..de82f86ad9a7db52924106735450f49ee8033a8c 100644 (file)
@@ -139,6 +139,57 @@ void Creature::Ingest(int res, double amount) noexcept {
                // 10% of fluids stays in body
                AddMass(res, amount * 0.05);
        }
+       math::GaloisLFSR &random = sim.Assets().random;
+       if (random.UNorm() < AdaptChance()) {
+               // change color to be slightly more like resource
+               glm::dvec3 color(rgb2hsl(sim.Resources()[res].base_color));
+               // solids affect base color, others highlight
+               double p = sim.Resources()[res].state == world::Resource::SOLID ? 0 : 1;
+               double q = random.UInt(3); // hue, sat, or val
+               double r = random.UInt(2); // mean or deviation
+               math::Distribution *d = nullptr;
+               double ref = 0.0;
+               if (p == 0) {
+                       if (q == 0) {
+                               d = &genome.base_hue;
+                               ref = color.x;
+                       } else if (q == 1) {
+                               d = &genome.base_saturation;
+                               ref = color.y;
+                       } else {
+                               d = &genome.base_lightness;
+                               ref = color.z;
+                       }
+               } else {
+                       if (q == 0) {
+                               d = &genome.highlight_hue;
+                               ref = color.x;
+                       } else if (q == 1) {
+                               d = &genome.highlight_saturation;
+                               ref = color.y;
+                       } else {
+                               d = &genome.highlight_lightness;
+                               ref = color.z;
+                       }
+               }
+               if (r == 0) {
+                       double diff = ref - d->Mean();
+                       if (q == 0) {
+                               if (diff < -0.5) {
+                                       diff += 1.0;
+                               } else if (diff > 0.5) {
+                                       diff -= 1.0;
+                               }
+                               // move ±15% of distance
+                               d->Mean(std::fmod(d->Mean() + diff * random.SNorm() * 0.15, 1.0));
+                       } else {
+                               d->Mean(glm::clamp(d->Mean() + diff * random.SNorm() * 0.15, 0.0, 1.0));
+                       }
+               } else {
+                       // scale by ±15%, enforce bounds
+                       d->StandardDeviation(glm::clamp(d->StandardDeviation() * (1.0 + random.SNorm() * 0.15), 0.0001, 0.5));
+               }
+       }
 }
 
 void Creature::DoWork(double amount) noexcept {
@@ -256,6 +307,10 @@ double Creature::Mutability() const noexcept {
        return properties.Mutability();
 }
 
+double Creature::Adaptability() const noexcept {
+       return properties.Adaptability();
+}
+
 double Creature::OffspringMass() const noexcept {
        return properties.OffspringMass();
 }
@@ -268,6 +323,10 @@ double Creature::MutateChance() const noexcept {
        return GetProperties().Mutability() * (1.0 / 3600.0);
 }
 
+double Creature::AdaptChance() const noexcept {
+       return GetProperties().Adaptability() * (1.0 / 120.0);
+}
+
 void Creature::AddGoal(std::unique_ptr<Goal> &&g) {
        g->Enable();
        goals.emplace_back(std::move(g));
@@ -546,7 +605,8 @@ void Spawn(Creature &c, world::Planet &p) {
        genome.properties.Intelligence() = { 1.0, 0.1 };
        genome.properties.Lifetime() = { 480.0, 60.0 };
        genome.properties.Fertility() = { 0.5, 0.03 };
-       genome.properties.Mutability() = { 1.0, 0.1 };
+       genome.properties.Mutability() = { 0.9, 0.1 };
+       genome.properties.Adaptability() = { 0.9, 0.1 };
        genome.properties.OffspringMass() = { 0.3, 0.02 };
 
        glm::dvec3 color_avg(0.0);
@@ -575,6 +635,10 @@ void Spawn(Creature &c, world::Planet &p) {
        genome.base_hue = { hsl.x, 0.01 };
        genome.base_saturation = { hsl.y, 0.01 };
        genome.base_lightness = { hsl.z, 0.01 };
+       // use opposite color as start highlight
+       genome.highlight_hue = { std::fmod(hsl.x + 0.5, 1.0), 0.01 };
+       genome.highlight_saturation = { 1.0 - hsl.y, 0.01 };
+       genome.highlight_lightness = { 1.0 - hsl.z, 0.01 };
 
        genome.Configure(c);
 }
@@ -601,9 +665,9 @@ void Genome::Configure(Creature &c) const {
                glm::clamp(base_lightness.FakeNormal(random.SNorm()), 0.0, 1.0)
        );
        glm::dvec3 highlight_color(
-               std::fmod(base_color.x + 0.5, 1.0),
-               1.0 - base_color.y,
-               1.0 - base_color.z
+               std::fmod(highlight_hue.FakeNormal(random.SNorm()) + 1.0, 1.0),
+               glm::clamp(highlight_saturation.FakeNormal(random.SNorm()), 0.0, 1.0),
+               glm::clamp(highlight_lightness.FakeNormal(random.SNorm()), 0.0, 1.0)
        );
        c.BaseColor(hsl2rgb(base_color));
        c.HighlightColor(hsl2rgb(highlight_color));
@@ -732,9 +796,9 @@ bool Situation::OnSurface() const noexcept {
 }
 
 bool Situation::OnTile() const noexcept {
+       if (type != PLANET_SURFACE) return false;
        glm::ivec2 t(planet->SurfacePosition(surface, state.pos));
-       return type == PLANET_SURFACE
-               && t.x >= 0 && t.x < planet->SideLength()
+       return t.x >= 0 && t.x < planet->SideLength()
                && t.y >= 0 && t.y < planet->SideLength();
 }
 
index 82ec757038f682354e8f5a11def83216dc830953..a4f33304f3f75af56b86c376b0c653879405006e 100644 (file)
@@ -111,7 +111,7 @@ void BlobBackgroundTask::CheckMutate() {
        // check for random property mutation
        if (GetCreature().MutateChance() > Assets().random.UNorm()) {
                double amount = 1.0 + (Assets().random.SNorm() * 0.05);
-               math::Distribution &d = GetCreature().GetGenome().properties.props[(int(Assets().random.UNorm() * 8.0) % 8)];
+               math::Distribution &d = GetCreature().GetGenome().properties.props[Assets().random.UInt(9)];
                if (Assets().random.UNorm() < 0.5) {
                        d.Mean(d.Mean() * amount);
                } else {
index d380e248405a2efb1ae9b65308d3b05b48e09e18..e2f39ebb5110eb348ea26f57dcb377933a0ee5e6 100644 (file)
@@ -63,6 +63,10 @@ public:
                return double(Next<std::uint64_t>()) * (1.0 / double(std::numeric_limits<std::uint64_t>::max()));
        }
 
+       unsigned int UInt(unsigned int below) noexcept {
+               return ((unsigned int)(UNorm() * double(below))) % below;
+       }
+
        template<class Container>
        typename Container::reference From(Container &c) {
                assert(c.size() > 0);
index 573804dff897ba09dcf926da90ffaee5c48d2d2c..92e81becc403ab102e520263d738751387e614c3 100644 (file)
@@ -55,7 +55,7 @@ private:
        Panel *composition;
        std::vector<Label *> components;
        Meter *stats[7];
-       Label *props[8];
+       Label *props[9];
        Panel panel;
 
 };
index 4cd660624cdeebd25f0f0f9c4c1a79278ca2c7bb..88d128877c3c900cffcbf5da15f4cdc8214dd264 100644 (file)
@@ -105,8 +105,8 @@ CreaturePanel::CreaturePanel(app::Assets &assets)
                ->Add(stat_label_panel)
                ->Add(stat_meter_panel);
 
-       Label *prop_label[8];
-       for (int i = 0; i < 8; ++i) {
+       Label *prop_label[9];
+       for (int i = 0; i < 9; ++i) {
                prop_label[i] = new Label(assets.fonts.medium);
                props[i] = new Label(assets.fonts.medium);
        }
@@ -117,7 +117,8 @@ CreaturePanel::CreaturePanel(app::Assets &assets)
        prop_label[4]->Text("Lifetime");
        prop_label[5]->Text("Fertility");
        prop_label[6]->Text("Mutability");
-       prop_label[7]->Text("Offspring mass");
+       prop_label[7]->Text("Adaptability");
+       prop_label[8]->Text("Offspring mass");
 
        Panel *prop_label_panel = new Panel;
        prop_label_panel
@@ -127,7 +128,7 @@ CreaturePanel::CreaturePanel(app::Assets &assets)
        prop_meter_panel
                ->Spacing(2)
                ->Direction(Panel::VERTICAL);
-       for (int i = 0; i < 8; ++i) {
+       for (int i = 0; i < 9; ++i) {
                prop_label_panel->Add(prop_label[i]);
                prop_meter_panel->Add(props[i]);
        }
@@ -235,7 +236,8 @@ void CreaturePanel::Draw(graphics::Viewport &viewport) noexcept {
        props[4]->Text(TimeString(c->Lifetime()));
        props[5]->Text(PercentageString(c->Fertility()));
        props[6]->Text(PercentageString(c->Mutability()));
-       props[7]->Text(MassString(c->OffspringMass()));
+       props[7]->Text(PercentageString(c->Adaptability()));
+       props[8]->Text(MassString(c->OffspringMass()));
 
        const glm::vec2 margin(20.0f);
        panel.Position(glm::vec2(viewport.Width() - margin.x - panel.Size().x, margin.y));