Video version
This commit is contained in:
Generated
-21
@@ -43,7 +43,6 @@ dependencies = [
|
||||
"colornamer",
|
||||
"itertools",
|
||||
"rand",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -141,26 +140,6 @@ dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.100"
|
||||
|
||||
@@ -7,4 +7,3 @@ edition = "2021"
|
||||
colornamer = "1.0.1"
|
||||
itertools = "0.14.0"
|
||||
rand = "0.9.1"
|
||||
serde = {version = "1.0.219", features=["derive"]}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rand::{rng, seq::IndexedRandom, Rng};
|
||||
use rand::{rng, seq::IndexedRandom};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum ChoiceFunction {
|
||||
@@ -9,6 +9,9 @@ pub enum ChoiceFunction {
|
||||
|
||||
impl ChoiceFunction {
|
||||
pub fn choose<'a, T>(&self, xs: &'a [T]) -> &'a T {
|
||||
if xs.len() == 0 {
|
||||
panic!("requires at least one item")
|
||||
}
|
||||
match self {
|
||||
ChoiceFunction::First => &xs[0],
|
||||
ChoiceFunction::Last => &xs[xs.len() - 1],
|
||||
|
||||
+14
-10
@@ -27,12 +27,12 @@ impl Genetic for Coloration {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Color {
|
||||
pub r: Stat<'.', '!', 0, 8>,
|
||||
pub g: Stat<'.', '!', 0, 8>,
|
||||
pub b: Stat<'.', '!', 0, 8>,
|
||||
pub pallor: Stat<'.', '!', 0, 8>,
|
||||
pub p: Stat<'.', '!', 0, 8>,
|
||||
}
|
||||
|
||||
impl Genetic for Color {
|
||||
@@ -40,21 +40,25 @@ impl Genetic for Color {
|
||||
self.r.transcribe(t.nest("r"));
|
||||
self.g.transcribe(t.nest("g"));
|
||||
self.b.transcribe(t.nest("b"));
|
||||
self.pallor.transcribe(t.nest("pallor"));
|
||||
self.p.transcribe(t.nest("p"));
|
||||
}
|
||||
}
|
||||
|
||||
impl Color {
|
||||
fn to_name(&self) -> String {
|
||||
pub fn to_rgb(&self) -> (u8, u8, u8) {
|
||||
let mut r = self.r.value() * 255 / 8;
|
||||
let mut g = self.g.value() * 255 / 8;
|
||||
let mut b = self.b.value() * 255 / 8;
|
||||
let pallor_amt = self.pallor.value() * 255 / 8;
|
||||
r = (r * (255 - pallor_amt) + 255 * pallor_amt) / 255;
|
||||
g = (g * (255 - pallor_amt) + 255 * pallor_amt) / 255;
|
||||
b = (b * (255 - pallor_amt) + 255 * pallor_amt) / 255;
|
||||
// let colornamer = ColorNamer::new(Colors::NTC);
|
||||
let colornamer = ColorNamer::new(Colors::X11);
|
||||
let p = self.p.value() * 255 / 8;
|
||||
|
||||
r = (r * (255 - p) + 0xd0 * p) / 255;
|
||||
g = (g * (255 - p) + 0xd0 * p) / 255;
|
||||
b = (b * (255 - p) + 0xd8 * p) / 255;
|
||||
return (r as u8, g as u8, b as u8);
|
||||
}
|
||||
pub fn to_name(&self) -> String {
|
||||
let colornamer = ColorNamer::new(Colors::NTC);
|
||||
let (r, g, b) = self.to_rgb();
|
||||
let hex_color = format!("#{:02x}{:02x}{:02x}", r, g, b);
|
||||
return format!(
|
||||
"{} ({})",
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
use crate::genetics::{Genetic, Transcriber};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub enum Gender {
|
||||
Male,
|
||||
Female,
|
||||
#[default]
|
||||
Other,
|
||||
}
|
||||
|
||||
impl Genetic for Gender {
|
||||
fn transcribe(&mut self, mut t: Transcriber) {
|
||||
t.express(
|
||||
self,
|
||||
&[
|
||||
('m', Gender::Male),
|
||||
('f', Gender::Female),
|
||||
('O', Gender::Other),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl Gender {
|
||||
pub fn profile(&self) -> String {
|
||||
format!("Gender: {:?}\n", self)
|
||||
}
|
||||
}
|
||||
+32
-47
@@ -1,62 +1,47 @@
|
||||
mod coloration;
|
||||
mod gender;
|
||||
mod phenotype;
|
||||
mod species;
|
||||
mod stats;
|
||||
|
||||
use coloration::Coloration;
|
||||
use species::Parts;
|
||||
use stats::Stats;
|
||||
use phenotype::Phenotype;
|
||||
|
||||
use crate::genetics::{Genetic, Genotype, Transcriber};
|
||||
use crate::{choice_function::ChoiceFunction, genetics::Genotype};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone)]
|
||||
pub struct Creature {
|
||||
// pub name: String,
|
||||
pub genotype: Genotype,
|
||||
genotype: Genotype,
|
||||
}
|
||||
|
||||
impl Creature {
|
||||
pub fn profile(&self) -> String {
|
||||
let phenotype: Phenotype = self.genotype.load();
|
||||
pub fn generate(choice_function: ChoiceFunction) -> Self {
|
||||
Creature {
|
||||
genotype: Genotype::generate::<Phenotype>(choice_function),
|
||||
}
|
||||
}
|
||||
|
||||
let mut profile = phenotype.profile(); // format!("Name: {}\n{}", self.name, phenotype.profile());
|
||||
profile.push_str("\nGenome:\n");
|
||||
for (chromosome, (lhs, rhs)) in self.genotype.chromosomes.iter() {
|
||||
profile.push_str(&format!(" {}[l]: {}\n", chromosome, lhs));
|
||||
profile.push_str(&format!(" {}[r]: {}\n", chromosome, rhs));
|
||||
pub fn breed(&self, choice_function: ChoiceFunction, other: &Creature) -> Creature {
|
||||
return Creature {
|
||||
genotype: self.genotype.breed(choice_function, &other.genotype),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn phenotype(&self) -> Phenotype {
|
||||
let phenotype: Phenotype = self.genotype.load();
|
||||
return phenotype;
|
||||
}
|
||||
|
||||
pub fn profile(&self) -> String {
|
||||
let phenotype: Phenotype = self.phenotype();
|
||||
let mut profile = phenotype.profile();
|
||||
if true {
|
||||
profile.push_str("\nGenome:\n");
|
||||
|
||||
for (chromosome, (lhs, rhs)) in self.genotype.chromosomes.iter() {
|
||||
profile.push_str(&format!(" {}[l]: {}\n", chromosome, lhs));
|
||||
profile.push_str(&format!(" {}[r]: {}\n", chromosome, rhs));
|
||||
}
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
|
||||
pub fn breed(&self, other: &Creature) -> Creature {
|
||||
return Creature {
|
||||
// name: String::from("Pyrex"),
|
||||
genotype: self.genotype.breed(&other.genotype),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Phenotype {
|
||||
pub stats: Stats,
|
||||
pub coloration: Coloration,
|
||||
pub parts: Parts,
|
||||
}
|
||||
|
||||
impl Phenotype {
|
||||
pub fn profile(&self) -> String {
|
||||
format!(
|
||||
"{}{}{}",
|
||||
self.stats.profile(),
|
||||
self.coloration.profile(),
|
||||
self.parts.profile()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Genetic for Phenotype {
|
||||
fn transcribe(&mut self, t: Transcriber) {
|
||||
self.stats.transcribe(t.nest("stats"));
|
||||
self.coloration.transcribe(t.nest("coloration"));
|
||||
self.parts.transcribe(t.nest("parts"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
use crate::genetics::{Genetic, Transcriber};
|
||||
|
||||
use super::{coloration::Coloration, gender::Gender, species::Parts, stats::Stats};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Phenotype {
|
||||
pub gender: Gender,
|
||||
pub parts: Parts,
|
||||
pub stats: Stats,
|
||||
pub coloration: Coloration,
|
||||
}
|
||||
|
||||
impl Phenotype {
|
||||
pub fn profile(&self) -> String {
|
||||
format!(
|
||||
"{}{}{}{}",
|
||||
self.gender.profile(),
|
||||
self.parts.profile(),
|
||||
self.stats.profile(),
|
||||
self.coloration.profile()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Genetic for Phenotype {
|
||||
fn transcribe(&mut self, t: Transcriber) {
|
||||
self.gender.transcribe(t.nest("gender"));
|
||||
self.parts.transcribe(t.nest("parts"));
|
||||
self.stats.transcribe(t.nest("stats"));
|
||||
self.coloration.transcribe(t.nest("coloration"));
|
||||
}
|
||||
}
|
||||
@@ -43,14 +43,6 @@ impl Parts {
|
||||
}
|
||||
}
|
||||
|
||||
impl Genetic for Parts {
|
||||
fn transcribe(&mut self, t: Transcriber) {
|
||||
self.stare.transcribe(t.nest("stare"));
|
||||
self.fangs.transcribe(t.nest("fangs"));
|
||||
self.wings.transcribe(t.nest("wings"));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Species {
|
||||
Bunny,
|
||||
@@ -62,3 +54,11 @@ pub enum Species {
|
||||
Snake,
|
||||
Bat,
|
||||
}
|
||||
|
||||
impl Genetic for Parts {
|
||||
fn transcribe(&mut self, t: Transcriber) {
|
||||
self.stare.transcribe(t.nest("stare"));
|
||||
self.fangs.transcribe(t.nest("fangs"));
|
||||
self.wings.transcribe(t.nest("wings"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ impl<const OFF: char, const ON: char, const MIN: usize, const RANGE: usize> Gene
|
||||
{
|
||||
fn transcribe(&mut self, mut t: Transcriber) {
|
||||
for v in self.values.iter_mut() {
|
||||
t.express(v, &[(OFF, false), (ON, true)]);
|
||||
t.express(v, &[(OFF, false), (ON, true)])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
mod transcriber;
|
||||
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
|
||||
use itertools::{EitherOrBoth, Itertools};
|
||||
pub use transcriber::Transcriber;
|
||||
|
||||
use crate::choice_function::{self, ChoiceFunction};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Genotype {
|
||||
pub chromosomes: BTreeMap<String, Chromosomes>,
|
||||
}
|
||||
|
||||
type Chromosomes = (String, String);
|
||||
|
||||
pub trait Genetic: Default {
|
||||
fn transcribe(&mut self, t: Transcriber);
|
||||
}
|
||||
|
||||
fn merge(choice_function: ChoiceFunction, one: &str, two: &str) -> String {
|
||||
let mut results = String::new();
|
||||
for pair in one.chars().zip_longest(two.chars()) {
|
||||
results.push(match pair {
|
||||
EitherOrBoth::Both(l, r) => *choice_function.choose(&[l, r]),
|
||||
EitherOrBoth::Left(l) => l,
|
||||
EitherOrBoth::Right(r) => r,
|
||||
});
|
||||
}
|
||||
results
|
||||
}
|
||||
|
||||
impl Genotype {
|
||||
pub fn breed(&self, choice_function: ChoiceFunction, other: &Genotype) -> Genotype {
|
||||
let mut chromosomes: HashSet<String> = HashSet::new();
|
||||
chromosomes.extend(self.chromosomes.keys().cloned());
|
||||
chromosomes.extend(other.chromosomes.keys().cloned());
|
||||
|
||||
let mut result: BTreeMap<String, Chromosomes> = BTreeMap::new();
|
||||
let placeholder = (String::new(), String::new());
|
||||
|
||||
for k in chromosomes {
|
||||
let mine = self.chromosomes.get(&k).unwrap_or(&placeholder);
|
||||
let theirs = self.chromosomes.get(&k).unwrap_or(&placeholder);
|
||||
|
||||
/*
|
||||
let mine_merged = merge(choice_function, &mine.0, &mine.1);
|
||||
let theirs_merged = merge(choice_function, &theirs.0, &theirs.1);
|
||||
result.insert(k, (mine_merged, theirs_merged));
|
||||
*/
|
||||
let my_choice = (*choice_function.choose(&[&mine.0, &mine.1])).clone();
|
||||
let their_choice = (*choice_function.choose(&[&theirs.0, &theirs.1])).clone();
|
||||
result.insert(k, (my_choice, their_choice));
|
||||
}
|
||||
return Genotype {
|
||||
chromosomes: result,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,74 +1,29 @@
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::{BTreeMap, HashSet},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use itertools::{EitherOrBoth, Itertools};
|
||||
use rand::{seq::IndexedRandom, RngCore};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{cell::RefCell, collections::BTreeMap};
|
||||
|
||||
use crate::choice_function::ChoiceFunction;
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize, Debug)]
|
||||
pub struct Genotype {
|
||||
pub chromosomes: BTreeMap<String, Chromosomes>,
|
||||
}
|
||||
type Chromosomes = (String, String);
|
||||
|
||||
fn merge(rng: &mut impl RngCore, one: &str, two: &str) -> String {
|
||||
let mut results = String::new();
|
||||
for pair in one.chars().zip_longest(two.chars()) {
|
||||
results.push(match pair {
|
||||
EitherOrBoth::Both(l, r) => *[l, r].choose(rng).unwrap(),
|
||||
EitherOrBoth::Left(l) => l,
|
||||
EitherOrBoth::Right(r) => r,
|
||||
})
|
||||
}
|
||||
return results;
|
||||
}
|
||||
use super::{Chromosomes, Genetic, Genotype};
|
||||
|
||||
impl Genotype {
|
||||
pub fn breed(&self, other: &Genotype) -> Genotype {
|
||||
let mut rng = rand::rng();
|
||||
let mut chromosomes: HashSet<String> = HashSet::new();
|
||||
chromosomes.extend(self.chromosomes.keys().cloned());
|
||||
chromosomes.extend(other.chromosomes.keys().cloned());
|
||||
|
||||
let mut result: BTreeMap<String, Chromosomes> = BTreeMap::new();
|
||||
let placeholder = (String::new(), String::new());
|
||||
for k in chromosomes {
|
||||
let mine = self.chromosomes.get(&k).unwrap_or(&placeholder);
|
||||
let theirs = self.chromosomes.get(&k).unwrap_or(&placeholder);
|
||||
|
||||
let mine_merged = merge(&mut rng, &mine.0, &mine.1);
|
||||
let theirs_merged = merge(&mut rng, &theirs.0, &theirs.1);
|
||||
result.insert(k, (mine_merged, theirs_merged));
|
||||
}
|
||||
return Genotype {
|
||||
chromosomes: result,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn generate<T: Genetic>(choice_function: ChoiceFunction) -> Self {
|
||||
let root = RootTranscriber::Generator(Generator {
|
||||
choice_function,
|
||||
progress: BTreeMap::new(),
|
||||
});
|
||||
let root_cell = Rc::new(RefCell::new(root));
|
||||
let root_cell = RefCell::new(root);
|
||||
let transcriber = Transcriber {
|
||||
root: root_cell.clone(),
|
||||
root: &root_cell,
|
||||
chromosome: String::from("base"),
|
||||
};
|
||||
let mut base = T::default();
|
||||
base.transcribe(transcriber);
|
||||
match &*root_cell.borrow() {
|
||||
match root_cell.into_inner() {
|
||||
RootTranscriber::Generator(generator) => {
|
||||
let chromosomes = generator.progress.clone();
|
||||
let chromosomes = generator.progress;
|
||||
return Genotype { chromosomes };
|
||||
}
|
||||
_ => panic!("a generator should not able to turn into a loader"),
|
||||
};
|
||||
_ => panic!("a generator should not be able to turn into anything else"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load<T: Genetic>(&self) -> T {
|
||||
@@ -76,13 +31,14 @@ impl Genotype {
|
||||
for (key, (lhs, rhs)) in self.chromosomes.iter() {
|
||||
progress.insert(
|
||||
key.clone(),
|
||||
// as a note: we could just store the character iterator!
|
||||
(0, Vec::from_iter(lhs.chars()), Vec::from_iter(rhs.chars())),
|
||||
);
|
||||
}
|
||||
let root = RootTranscriber::Loader(Loader { progress });
|
||||
let root_cell = Rc::new(RefCell::new(root));
|
||||
let root_cell = RefCell::new(root);
|
||||
let transcriber = Transcriber {
|
||||
root: root_cell.clone(),
|
||||
root: &root_cell,
|
||||
chromosome: String::from("base"),
|
||||
};
|
||||
let mut base = T::default();
|
||||
@@ -104,21 +60,20 @@ impl RootTranscriber {
|
||||
possibilities: &[(char, T)],
|
||||
) {
|
||||
match self {
|
||||
RootTranscriber::Generator(generator) => {
|
||||
generator.express(chromosome, field, possibilities)
|
||||
RootTranscriber::Generator(generator) => generator.express(chromosome, possibilities),
|
||||
RootTranscriber::Loader(loader) => {
|
||||
loader.express(chromosome, field, possibilities);
|
||||
}
|
||||
RootTranscriber::Loader(loader) => loader.express(chromosome, field, possibilities),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Transcriber {
|
||||
root: Rc<RefCell<RootTranscriber>>,
|
||||
pub struct Transcriber<'r> {
|
||||
root: &'r RefCell<RootTranscriber>,
|
||||
chromosome: String,
|
||||
}
|
||||
|
||||
impl Transcriber {
|
||||
impl Transcriber<'_> {
|
||||
pub fn express<T: Clone>(&mut self, field: &mut T, possibilities: &[(char, T)]) {
|
||||
self.root
|
||||
.borrow_mut()
|
||||
@@ -127,33 +82,28 @@ impl Transcriber {
|
||||
|
||||
pub fn nest(&self, suffix: &str) -> Transcriber {
|
||||
return Transcriber {
|
||||
root: self.root.clone(),
|
||||
root: self.root,
|
||||
chromosome: format!("{}.{}", self.chromosome, suffix),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Genetic: Default {
|
||||
fn transcribe(&mut self, t: Transcriber);
|
||||
}
|
||||
|
||||
struct Generator {
|
||||
choice_function: ChoiceFunction,
|
||||
progress: BTreeMap<String, Chromosomes>,
|
||||
}
|
||||
|
||||
impl Generator {
|
||||
pub fn express<T>(&mut self, chromosome: &str, _field: &mut T, possibilities: &[(char, T)]) {
|
||||
let lhs = self.choice_function.choose(possibilities).0;
|
||||
let rhs = self.choice_function.choose(possibilities).0;
|
||||
pub fn express<T>(&mut self, chromosome: &str, possibilities: &[(char, T)]) {
|
||||
let lhs = self.choice_function.choose(possibilities);
|
||||
let rhs = self.choice_function.choose(possibilities);
|
||||
|
||||
let progress = self
|
||||
.progress
|
||||
.entry(chromosome.to_string())
|
||||
.entry(chromosome.to_string()) // SLOW!
|
||||
.or_insert((String::new(), String::new()));
|
||||
|
||||
progress.0.push(lhs);
|
||||
progress.1.push(rhs);
|
||||
progress.0.push(lhs.0);
|
||||
progress.1.push(rhs.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +125,7 @@ impl Loader {
|
||||
*ix += 1;
|
||||
}
|
||||
|
||||
let mut expressed = lhs; // lhs wins if not dominated
|
||||
let mut expressed = lhs;
|
||||
if dominance(rhs) > dominance(lhs) {
|
||||
expressed = rhs;
|
||||
}
|
||||
+15
-23
@@ -1,53 +1,48 @@
|
||||
use choice_function::ChoiceFunction;
|
||||
use creature::{Creature, Phenotype};
|
||||
use genetics::Genotype;
|
||||
use creature::Creature;
|
||||
use rand::{rng, seq::SliceRandom};
|
||||
|
||||
mod choice_function;
|
||||
mod creature;
|
||||
mod genetics;
|
||||
|
||||
fn generate_creature() -> Creature {
|
||||
let genotype: Genotype = Genotype::generate::<Phenotype>(ChoiceFunction::Random);
|
||||
let creature = Creature {
|
||||
// name: String::from("Pyrex"),
|
||||
genotype,
|
||||
};
|
||||
return creature;
|
||||
}
|
||||
|
||||
fn evolve() {
|
||||
let cf = ChoiceFunction::Random;
|
||||
const N_ITERATIONS: usize = 200;
|
||||
const N_CREATURES: usize = 100;
|
||||
const N_SURVIVORS: usize = 90;
|
||||
const N_RANDOMS: usize = 50;
|
||||
const N_SURVIVORS: usize = 40;
|
||||
|
||||
let mut pool = vec![];
|
||||
for _ in 0..N_CREATURES {
|
||||
pool.push(generate_creature());
|
||||
pool.push(Creature::generate(cf));
|
||||
}
|
||||
|
||||
for iteration in 0..N_ITERATIONS {
|
||||
report(iteration, &pool);
|
||||
|
||||
// kill N creatures
|
||||
let mut survivors = pool.clone();
|
||||
let mut survivors = pool;
|
||||
survivors.sort_by(|x, y| fitness(x).partial_cmp(&fitness(y)).unwrap());
|
||||
survivors.reverse();
|
||||
survivors.drain(N_SURVIVORS..N_CREATURES);
|
||||
|
||||
let mut pool2 = vec![];
|
||||
for _ in 0..N_RANDOMS {
|
||||
survivors.push(Creature::generate(cf));
|
||||
}
|
||||
|
||||
let mut survivors_queue = vec![];
|
||||
while survivors_queue.len() < N_CREATURES * 2 {
|
||||
survivors_queue.extend(survivors.clone());
|
||||
}
|
||||
survivors_queue.shuffle(&mut rng());
|
||||
|
||||
let mut offspring = vec![];
|
||||
for _ in 0..N_CREATURES {
|
||||
let lhs = survivors_queue.pop().unwrap();
|
||||
let rhs = survivors_queue.pop().unwrap();
|
||||
pool2.push(lhs.breed(&rhs));
|
||||
offspring.push(lhs.breed(cf, &rhs));
|
||||
}
|
||||
pool = pool2;
|
||||
pool = offspring;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,13 +53,10 @@ fn report(iteration: usize, pool: &[Creature]) {
|
||||
}
|
||||
|
||||
fn fitness(creature: &Creature) -> f64 {
|
||||
let phenotype: Phenotype = creature.genotype.load();
|
||||
let phenotype = creature.phenotype();
|
||||
let mut value = 0.0;
|
||||
if phenotype.parts.has_wings() {
|
||||
value += 0.5;
|
||||
}
|
||||
value -= phenotype.coloration.body.r.value() as f64 / 4.0;
|
||||
value += (phenotype.stats.iq.value() as f64) / 10.0;
|
||||
value += (phenotype.stats.eq.value() as f64) / 10.0;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 280 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 238 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 425 KiB |
Binary file not shown.
Reference in New Issue
Block a user