Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.DS_Store
/.vscode
/target
output.brain
31 changes: 31 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ egui-macroquad = "0.15.0"
macroquad = "0.3.25"
once_cell = "1.17.1"
rand = "0.8.5"
serde = { version = "1.0", features = ["derive"] }
bincode = "1.3.3"
18 changes: 18 additions & 0 deletions src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ impl Bird {
}
}

pub fn with_net(net: &Net) -> Self {
let mut new_bird = Bird::new();
new_bird.brain = net.clone();
new_bird
}

pub fn with_brain(other: &Bird) -> Self {
let mut new_bird = Bird::new();
new_bird.brain = other.brain.clone();
Expand Down Expand Up @@ -107,6 +113,18 @@ impl Bird {
self.brain.mutate();
}

pub fn save(&self) {
self.brain
.save_to_disk("output.brain")
.expect("Failed to save brain file");
}

pub fn load(&self) -> Net {
self.brain
.load_from_disk("output.brain")
.expect("Failed to load brain")
}

fn mark_dead(&mut self) {
self.is_dead = true;
}
Expand Down
10 changes: 10 additions & 0 deletions src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub struct Settings {
pub is_frame_skip: bool,
pub is_show_egui: bool,
pub show_one_bird: bool,
pub save: bool,
pub load: bool,
}

pub struct Editor {
Expand All @@ -25,6 +27,8 @@ impl Settings {
is_frame_skip: false,
is_show_egui: true,
show_one_bird: false,
save: false,
load: false,
}
}
}
Expand Down Expand Up @@ -83,6 +87,12 @@ impl Editor {
if ui.add(egui::Button::new("Restart")).clicked() {
self.settings.is_restart = true;
}
if ui.add(egui::Button::new("Save")).clicked() {
self.settings.save = true;
}
if ui.add(egui::Button::new("Load")).clicked() {
self.settings.load = true;
}
});
});
});
Expand Down
8 changes: 8 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ async fn main() {
stats = simulation.update(&editor.settings).unwrap_or(stats);
}
}
if editor.settings.save {
editor.settings.save = false;
simulation.save();
}
if editor.settings.load {
editor.settings.load = false;
simulation.load();
}

if is_key_pressed(KeyCode::Q) {
break;
Expand Down
19 changes: 17 additions & 2 deletions src/nn.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use macroquad::rand::gen_range;
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io::{self, BufReader, BufWriter};

use crate::*;

#[derive(Clone)]
#[derive(Clone, Serialize, Deserialize)]
pub struct Net {
n_inputs: usize,
layers: Vec<Layer>,
}

#[derive(Clone)]
#[derive(Clone, Serialize, Deserialize)]
struct Layer {
nodes: Vec<Vec<f64>>,
}
Expand Down Expand Up @@ -57,6 +60,18 @@ impl Net {
pub fn mutate(&mut self) {
self.layers.iter_mut().for_each(|l| l.mutate());
}

pub fn save_to_disk(&self, filename: &str) -> io::Result<()> {
let file = File::create(filename)?;
let writer = BufWriter::new(file);
bincode::serialize_into(writer, self).map_err(|e| io::Error::new(io::ErrorKind::Other, e))
}

pub fn load_from_disk(&self, filename: &str) -> io::Result<Self> {
let file = File::open(filename)?;
let reader = BufReader::new(file);
bincode::deserialize_from(reader).map_err(|e| io::Error::new(io::ErrorKind::Other, e))
}
}

impl Layer {
Expand Down
18 changes: 18 additions & 0 deletions src/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,24 @@ impl Simulation {
self.birds.iter().for_each(|b| b.draw());
}

pub fn save(&self) {
let bird = self.birds.iter().filter(|b| !b.is_dead).next().unwrap();
bird.save();
}

pub fn load(&mut self) -> () {
let bird = self.birds.first().unwrap();
let net = bird.load();
let mut new_birds = Vec::new();

for _ in 0..NUM_BIRDS {
let mut new_bird = Bird::with_net(&net);
new_bird.mutate();
new_birds.push(new_bird);
}
self.birds = new_birds;
}

fn selection(&self) -> Vec<Bird> {
let mut rng = thread_rng();
let gene_pool = self.calc_fitness();
Expand Down