diff --git a/CMakeLists.txt b/CMakeLists.txt
index af368e1..d4aa351 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,5 @@
cmake_minimum_required(VERSION 3.7)
-
option(VERSION_STRING "Project version string" "0.0.0")
project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX)
diff --git a/src/entity/components/genome.hpp b/src/entity/components/genome.hpp
new file mode 100644
index 0000000..a1941f0
--- /dev/null
+++ b/src/entity/components/genome.hpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 Christopher J. Howard
+ *
+ * This file is part of Antkeeper source code.
+ *
+ * Antkeeper source code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Antkeeper source code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Antkeeper source code. If not, see .
+ */
+
+#ifndef ANTKEEPER_ENTITY_COMPONENT_GENOME_HPP
+#define ANTKEEPER_ENTITY_COMPONENT_GENOME_HPP
+
+#include
+#include
+
+namespace entity {
+namespace component {
+
+/// Complete set of genetic material in an organism.
+struct genome
+{
+ /**
+ * Number of complete sets of chromosomes in a cell.
+ *
+ * A value of `1` indicates the organism is haploid, `2` is diploid, `3` is triploid, etc.
+ */
+ unsigned int ploidy;
+
+ /**
+ * Set of DNA base sequences for every chromosomes in the genome.
+ *
+ * A DNA base sequence is a string of IUPAC DNA base symbols. Homologous chromosomes should be stored consecutively, such that in a diploid organism, a chromosome with an even index is homologous to the following chromosome.
+ */
+ std::vector chromosomes;
+};
+
+} // namespace component
+} // namespace entity
+
+#endif // ANTKEEPER_ENTITY_COMPONENT_GENOME_HPP
diff --git a/src/entity/components/proteome.hpp b/src/entity/components/proteome.hpp
new file mode 100644
index 0000000..5d6e184
--- /dev/null
+++ b/src/entity/components/proteome.hpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 Christopher J. Howard
+ *
+ * This file is part of Antkeeper source code.
+ *
+ * Antkeeper source code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Antkeeper source code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Antkeeper source code. If not, see .
+ */
+
+#ifndef ANTKEEPER_ENTITY_COMPONENT_PROTEOME_HPP
+#define ANTKEEPER_ENTITY_COMPONENT_PROTEOME_HPP
+
+#include
+#include
+
+namespace entity {
+namespace component {
+
+/// Set of all proteins that can be expressed by an organism.
+struct proteome
+{
+ /// Set of amino acid sequences of every protein in the proteome.
+ std::vector proteins;
+};
+
+} // namespace component
+} // namespace entity
+
+#endif // ANTKEEPER_ENTITY_COMPONENT_PROTEOME_HPP
diff --git a/src/entity/systems/morphogenesis.cpp b/src/entity/systems/morphogenesis.cpp
new file mode 100644
index 0000000..fa6da0e
--- /dev/null
+++ b/src/entity/systems/morphogenesis.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 Christopher J. Howard
+ *
+ * This file is part of Antkeeper source code.
+ *
+ * Antkeeper source code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Antkeeper source code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Antkeeper source code. If not, see .
+ */
+
+#include "entity/systems/morphogenesis.hpp"
+#include "entity/id.hpp"
+
+namespace entity {
+namespace system {
+
+morphogenesis::morphogenesis(entity::registry& registry):
+ updatable(registry)
+{}
+
+void morphogenesis::update(double t, double dt)
+{}
+
+} // namespace system
+} // namespace entity
diff --git a/src/entity/systems/morphogenesis.hpp b/src/entity/systems/morphogenesis.hpp
new file mode 100644
index 0000000..86fbbc5
--- /dev/null
+++ b/src/entity/systems/morphogenesis.hpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 Christopher J. Howard
+ *
+ * This file is part of Antkeeper source code.
+ *
+ * Antkeeper source code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Antkeeper source code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Antkeeper source code. If not, see .
+ */
+
+#ifndef ANTKEEPER_ENTITY_SYSTEM_MORPHOGENESIS_HPP
+#define ANTKEEPER_ENTITY_SYSTEM_MORPHOGENESIS_HPP
+
+#include "entity/systems/updatable.hpp"
+
+namespace entity {
+namespace system {
+
+/**
+ * Constructs the forms of organisms from their genetic codes.
+ *
+ * Algorithm:
+ *
+ * 1. Consider inital egg cell as a sphere at the origin.
+ * 2. Use the marching cubes algorithm to generate a mesh from the isosurface formed by the sum of all cells.
+ * 3. Generate evenly-distributed points across surface area of the mesh (Poisson sample?).
+ * 4. For each point, evaluate morphogenic genes to determine type, direction, and color of the next cell.
+ * 5. Create new cells given the output of step 4.
+ * 6. Go to step 2 and repeat.
+ */
+class morphogenesis:
+ public updatable
+{
+public:
+ morphogenesis(entity::registry& registry);
+
+ /**
+ * Scales then adds the timestep `dt` to the current time, then recalculates the positions of morphogenesising bodies.
+ *
+ * @param t Time, in seconds.
+ * @param dt Delta time, in seconds.
+ */
+ virtual void update(double t, double dt);
+
+private:
+};
+
+} // namespace system
+} // namespace entity
+
+#endif // ANTKEEPER_ENTITY_SYSTEM_MORPHOGENESIS_HPP
diff --git a/src/entity/systems/proteome.cpp b/src/entity/systems/proteome.cpp
new file mode 100644
index 0000000..73bde69
--- /dev/null
+++ b/src/entity/systems/proteome.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 Christopher J. Howard
+ *
+ * This file is part of Antkeeper source code.
+ *
+ * Antkeeper source code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Antkeeper source code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Antkeeper source code. If not, see .
+ */
+
+#include "entity/systems/proteome.hpp"
+#include "entity/components/proteome.hpp"
+#include "genetics/sequence.hpp"
+#include "genetics/standard-code.hpp"
+
+namespace entity {
+namespace system {
+
+proteome::proteome(entity::registry& registry):
+ updatable(registry)
+{
+ registry.on_construct().connect<&proteome::on_genome_construct>(this);
+ registry.on_replace().connect<&proteome::on_genome_replace>(this);
+}
+
+void proteome::update(double t, double dt)
+{}
+
+void proteome::on_genome_construct(entity::registry& registry, entity::id entity_id, entity::component::genome& genome)
+{
+ on_genome_replace(registry, entity_id, genome);
+}
+
+void proteome::on_genome_replace(entity::registry& registry, entity::id entity_id, entity::component::genome& genome)
+{
+ // Allocate a proteome component
+ entity::component::proteome proteome_component;
+
+ // For each chromosome in the genome
+ for (const std::string& chromosome: genome.chromosomes)
+ {
+ // Find the first ORF in the chromosome
+ auto orf = genetics::sequence::find_orf(chromosome.begin(), chromosome.end(), genetics::standard_code);
+
+ // While the ORF is valid
+ while (orf.start != chromosome.end())
+ {
+ // Translate the base sequence into an amino acid sequence (protein)
+ std::string protein;
+ genetics::sequence::translate(orf.start, orf.stop, std::back_inserter(protein), genetics::standard_code);
+
+ // Append protein to the proteome
+ proteome_component.proteins.push_back(protein);
+
+ // Find the next ORF
+ orf = genetics::sequence::find_orf(orf.stop, chromosome.end(), genetics::standard_code);
+ }
+ }
+
+ // Assign or replace the entity's proteome component
+ registry.assign_or_replace(entity_id, proteome_component);
+}
+
+} // namespace system
+} // namespace entity
diff --git a/src/entity/systems/proteome.hpp b/src/entity/systems/proteome.hpp
new file mode 100644
index 0000000..567fbf4
--- /dev/null
+++ b/src/entity/systems/proteome.hpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 Christopher J. Howard
+ *
+ * This file is part of Antkeeper source code.
+ *
+ * Antkeeper source code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Antkeeper source code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Antkeeper source code. If not, see .
+ */
+
+#ifndef ANTKEEPER_ENTITY_SYSTEM_PROTEOME_HPP
+#define ANTKEEPER_ENTITY_SYSTEM_PROTEOME_HPP
+
+#include "entity/systems/updatable.hpp"
+#include "entity/components/genome.hpp"
+#include "entity/id.hpp"
+
+namespace entity {
+namespace system {
+
+/**
+ * Generates proteomes for every genome.
+ */
+class proteome:
+ public updatable
+{
+public:
+ proteome(entity::registry& registry);
+
+ /**
+ * Scales then adds the timestep `dt` to the current time, then recalculates the positions of proteomeing bodies.
+ *
+ * @param t Time, in seconds.
+ * @param dt Delta time, in seconds.
+ */
+ virtual void update(double t, double dt);
+
+private:
+ void on_genome_construct(entity::registry& registry, entity::id entity_id, entity::component::genome& genome);
+ void on_genome_replace(entity::registry& registry, entity::id entity_id, entity::component::genome& genome);
+};
+
+} // namespace system
+} // namespace entity
+
+#endif // ANTKEEPER_ENTITY_SYSTEM_PROTEOME_HPP
diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp
index ea89ca3..323513d 100644
--- a/src/game/bootloader.cpp
+++ b/src/game/bootloader.cpp
@@ -77,6 +77,7 @@
#include "entity/systems/blackbody.hpp"
#include "entity/systems/atmosphere.hpp"
#include "entity/systems/orbit.hpp"
+#include "entity/systems/proteome.hpp"
#include "entity/components/marker.hpp"
#include "entity/commands.hpp"
#include "utility/paths.hpp"
@@ -878,6 +879,9 @@ void setup_systems(game_context* ctx)
// Setup astronomy system
ctx->astronomy_system = new entity::system::astronomy(*ctx->entity_registry);
+ // Setup proteome system
+ ctx->proteome_system = new entity::system::proteome(*ctx->entity_registry);
+
// Set time scale
float time_scale = 60.0f;
if (ctx->config->has("time_scale"))
@@ -1277,7 +1281,7 @@ void setup_callbacks(game_context* ctx)
ctx->constraint_system->update(t, dt);
ctx->tracking_system->update(t, dt);
ctx->painting_system->update(t, dt);
-
+ ctx->proteome_system->update(t, dt);
//(*ctx->focal_point_tween)[1] = ctx->orbit_cam->get_focal_point();
@@ -1295,8 +1299,6 @@ void setup_callbacks(game_context* ctx)
ctx->application_controls->update();
ctx->menu_controls->update();
ctx->camera_controls->update();
-
-
}
);
diff --git a/src/game/game-context.hpp b/src/game/game-context.hpp
index c4d54de..df64b71 100644
--- a/src/game/game-context.hpp
+++ b/src/game/game-context.hpp
@@ -99,6 +99,7 @@ namespace entity
class nest;
class render;
class samara;
+ class proteome;
}
}
@@ -255,6 +256,7 @@ struct game_context
entity::system::atmosphere* atmosphere_system;
entity::system::astronomy* astronomy_system;
entity::system::orbit* orbit_system;
+ entity::system::proteome* proteome_system;
// Game
biome* biome;
diff --git a/src/game/states/play-state.cpp b/src/game/states/play-state.cpp
index 0a7beb2..714b28d 100644
--- a/src/game/states/play-state.cpp
+++ b/src/game/states/play-state.cpp
@@ -26,6 +26,7 @@
#include "entity/components/copy-transform.hpp"
#include "entity/components/copy-translation.hpp"
#include "entity/components/model.hpp"
+#include "entity/components/genome.hpp"
#include "entity/components/snap.hpp"
#include "entity/components/terrain.hpp"
#include "entity/components/tool.hpp"
@@ -362,13 +363,20 @@ void play_state_enter(game_context* ctx)
// Place larva in chamber
{
- auto larva = larva_archetype->create(entity_registry);
- entity::command::assign_render_layers(entity_registry, larva, 1);
- entity::command::warp_to(entity_registry, larva, {50, 0.1935f, 0});
+ auto larva_eid = larva_archetype->create(entity_registry);
+ entity::command::assign_render_layers(entity_registry, larva_eid, 1);
+ entity::command::warp_to(entity_registry, larva_eid, {50, 0.1935f, 0});
//auto& transform = entity_registry.get(larva_entity);
//transform.transform = math::identity_transform;
//transform.transform.translation = nest->get_shaft_position(*central_shaft, central_shaft->depth[1]);
//transform.transform.translation.y -= 1.0f;
+
+ // Construct larva genome
+ entity::component::genome genome;
+ genome.ploidy = 2;
+ const std::string antp = "ATGACCATGAGCACCAACAACTGCGAAAGCATGACCAGCTATTTTACCAACAGCTATATGGGCGCGGATATGCATCATGGCCATTATCCGGGCAACGGCGTGACCGATCTGGATGCGCAGCAGATGCATCATTATAGCCAGAACGCGAACCATCAGGGCAACATGCCGTATCCGCGCTTTCCGCCGTATGATCGCATGCCGTATTATAACGGCCAGGGCATGGATCAGCAGCAGCAGCATCAGGTGTATAGCCGCCCGGATAGCCCGAGCAGCCAGGTGGGCGGCGTGATGCCGCAGGCGCAGACCAACGGCCAGCTGGGCGTGCCGCAGCAGCAGCAGCAGCAGCAGCAGCAGCCGAGCCAGAACCAGCAGCAGCAGCAGGCGCAGCAGGCGCCGCAGCAGCTGCAGCAGCAGCTGCCGCAGGTGACCCAGCAGGTGACCCATCCGCAGCAGCAGCAGCAGCAGCCGGTGGTGTATGCGAGCTGCAAACTGCAGGCGGCGGTGGGCGGCCTGGGCATGGTGCCGGAAGGCGGCAGCCCGCCGCTGGTGGATCAGATGAGCGGCCATCATATGAACGCGCAGATGACCCTGCCGCATCATATGGGCCATCCGCAGGCGCAGGTGCATCAGAACCATCATAACATGGGCATGTATCAGCAGCAGAGCGGCGTGCCGCCGGTGGGCGCGCCGCCGCAGGGCATGATGCATCAGGGCCAGGGCCCGCCGCAGATGCATCAGGGCCATCCGGGCCAGCATACCCCGCCGAGCCAGAACCCGAACAGCCAGAGCAGCGGCATGCCGAGCCCGCTGTATCCGTGGATGCGCAGCCAGTTTGAACGCAAACGCGGCCGCCAGACCTATACCCGCTATCAGACCCTGGAACTGGAAAAAGAATTTCATTTTAACCGCTATCTGACCCGCCGCCGCCGCATTGAAATTGCGCATGCGCTGTGCCTGACCGAACGCCAGATTAAAATTTGGTTTCAGAACCGCCGCATGAAATGGAAAAAAGAAAACAAAACCAAAGGCGAACCGGGCAGCGGCGGCGAAGGCGATGAAATTACCCCGCCGAACAGCCCGCAGTAG";
+ genome.chromosomes.push_back(antp);
+ entity_registry.assign(larva_eid, genome);
}
entity::system::control* control_system = ctx->control_system;
@@ -382,62 +390,6 @@ void play_state_enter(game_context* ctx)
std::string biome_name = (*ctx->strings)[ctx->biome->name];
logger->log("Entered biome \"" + biome_name + "\"");
-
-
- std::srand(std::time(nullptr));
- //auto rng = [](){ return std::rand(); };
-
- std::random_device rd;
- std::mt19937 rng(rd());
-
-
- std::string sequence_a = "CCTTGCCCTTTGGGTCGCCCCCCTAG";
- std::string sequence_b = "ATGTTTCCCGAAGGGTAG";
- std::string sequence_c = "AAATGCCCCCCCCCCCCCCCCCCCCCCCCCCCTAGAAAAAAAAA";
- std::string orf_a;
- std::string protein_a;
- std::string protein_b;
- std::string protein_c;
-
-
- std::cout << "sequence a: " << sequence_a << std::endl;
- genetics::sequence::transcribe(sequence_a.begin(), sequence_a.end(), sequence_a.begin());
- std::cout << "sequence a: " << sequence_a << std::endl;
-
- std::string complement;
- genetics::sequence::rna::complement(sequence_a.begin(), sequence_a.end(), std::back_inserter(complement));
- std::cout << "complement: " << complement << std::endl;
-
- auto orf = genetics::sequence::find_orf(sequence_a.begin(), sequence_a.end(), genetics::standard_code);
- if (orf.start != sequence_a.end())
- {
- std::copy(orf.start, orf.stop, std::back_inserter(orf_a));
- std::cout << "orf a: " << orf_a << std::endl;
-
- genetics::sequence::translate(orf.start, orf.stop, std::back_inserter(protein_a), genetics::standard_code);
- std::cout << "protein a: " << protein_a << std::endl;
- }
-
- protein_b = "MFFFFP";
- protein_c = "MFFFYP";
- int score;
-
- std::cout << std::endl;
- std::cout << "protein_b: " << protein_b << std::endl;
- std::cout << "protein_c: " << protein_c << std::endl;
-
- score = genetics::protein::score(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum62);
- std::cout << "score blosum62: " << score << std::endl;
-
- score = genetics::protein::score(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum80);
- std::cout << "score blosum80: " << score << std::endl;
-
-
- std::cout << "identity : " << genetics::protein::identity(protein_b.begin(), protein_b.end(), protein_c.begin()) << std::endl;
- std::cout << "similarity62: " << genetics::protein::similarity(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum62) << std::endl;
- std::cout << "similarity80: " << genetics::protein::similarity(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum80) << std::endl;
-
-
}
void play_state_exit(game_context* ctx)