Video version
This commit is contained in:
parent
b323eef0e2
commit
4df78304d0
21
Cargo.lock
generated
21
Cargo.lock
generated
@ -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],
|
||||
|
@ -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!(
|
||||
"{} ({})",
|
||||
|
28
src/creature/gender.rs
Normal file
28
src/creature/gender.rs
Normal file
@ -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)
|
||||
}
|
||||
}
|
@ -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());
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
32
src/creature/phenotype.rs
Normal file
32
src/creature/phenotype.rs
Normal file
@ -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)])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
59
src/genetics/mod.rs
Normal file
59
src/genetics/mod.rs
Normal file
@ -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;
|
||||
}
|
38
src/main.rs
38
src/main.rs
@ -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;
|
||||
}
|
||||
|
BIN
thumbnail.png
Normal file
BIN
thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 280 KiB |
BIN
thumbnail.xcf
Normal file
BIN
thumbnail.xcf
Normal file
Binary file not shown.
BIN
thumbnail2.png
Normal file
BIN
thumbnail2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 238 KiB |
BIN
thumbnail2.xcf
Normal file
BIN
thumbnail2.xcf
Normal file
Binary file not shown.
BIN
thumbnail3.xcf
Normal file
BIN
thumbnail3.xcf
Normal file
Binary file not shown.
BIN
thumbnail4.png
Normal file
BIN
thumbnail4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 425 KiB |
BIN
thumbnail4.xcf
Normal file
BIN
thumbnail4.xcf
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user