tracking ui
This commit is contained in:
parent
b7ad50da37
commit
0796eda239
96
src/main.rs
96
src/main.rs
|
@ -11,7 +11,7 @@ use macroquad::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
ui::{hash, root_ui, widgets, Skin},
|
ui::{hash, root_ui, widgets, Skin},
|
||||||
};
|
};
|
||||||
use population::Population;
|
use population::{AutoSwitch, Population};
|
||||||
use world::World;
|
use world::World;
|
||||||
|
|
||||||
pub const WIDTH: f32 = 800.;
|
pub const WIDTH: f32 = 800.;
|
||||||
|
@ -76,8 +76,15 @@ async fn main() {
|
||||||
ActivationFunc::Sigmoid,
|
ActivationFunc::Sigmoid,
|
||||||
ActivationFunc::Tanh,
|
ActivationFunc::Tanh,
|
||||||
];
|
];
|
||||||
|
let mut auto_switch = Some(AutoSwitch::Best);
|
||||||
|
|
||||||
let mut pop = Population::new(size as usize, hlayers.clone(), mut_rate, activs[activ]);
|
let mut pop = Population::new(
|
||||||
|
size as usize,
|
||||||
|
auto_switch,
|
||||||
|
hlayers.clone(),
|
||||||
|
mut_rate,
|
||||||
|
activs[activ],
|
||||||
|
);
|
||||||
|
|
||||||
let ui_thick = 34.;
|
let ui_thick = 34.;
|
||||||
let nums = &[
|
let nums = &[
|
||||||
|
@ -192,15 +199,36 @@ async fn main() {
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
.background_margin(RectOffset::new(1., 1., 1., 1.))
|
.background_margin(RectOffset::new(1., 1., 1., 1.))
|
||||||
.color_hovered(RED)
|
.color_hovered(GREEN)
|
||||||
.color_clicked(BLUE)
|
.color_clicked(GREEN)
|
||||||
.text_color(WHITE)
|
.text_color(WHITE)
|
||||||
.text_color_hovered(WHITE)
|
.text_color_hovered(WHITE)
|
||||||
.text_color_clicked(WHITE)
|
.text_color_clicked(GREEN)
|
||||||
.margin(RectOffset::new(4., 4., 2., 2.))
|
.margin(RectOffset::new(4., 4., 2., 2.))
|
||||||
.color_inactive(WHITE)
|
.color_inactive(WHITE)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
let mut skin3 = skin2.clone();
|
||||||
|
skin3.button_style = root_ui()
|
||||||
|
.style_builder()
|
||||||
|
.background(Image {
|
||||||
|
width: 3,
|
||||||
|
height: 3,
|
||||||
|
bytes: vec![
|
||||||
|
0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 0, 0, 255, 0,
|
||||||
|
255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.background_margin(RectOffset::new(1., 1., 1., 1.))
|
||||||
|
.color_hovered(GREEN)
|
||||||
|
.color_clicked(GREEN)
|
||||||
|
.text_color(GREEN)
|
||||||
|
.text_color_hovered(GREEN)
|
||||||
|
.text_color_clicked(GREEN)
|
||||||
|
.margin(RectOffset::new(4., 4., 2., 2.))
|
||||||
|
.color_inactive(GREEN)
|
||||||
|
.build();
|
||||||
|
|
||||||
root_ui().push_skin(&skin);
|
root_ui().push_skin(&skin);
|
||||||
loop {
|
loop {
|
||||||
clear_background(BLACK);
|
clear_background(BLACK);
|
||||||
|
@ -297,6 +325,7 @@ async fn main() {
|
||||||
|
|
||||||
pop = Population::new(
|
pop = Population::new(
|
||||||
size as usize,
|
size as usize,
|
||||||
|
auto_switch,
|
||||||
hlayers.clone(),
|
hlayers.clone(),
|
||||||
mut_rate,
|
mut_rate,
|
||||||
activs[activ],
|
activs[activ],
|
||||||
|
@ -360,6 +389,7 @@ async fn main() {
|
||||||
if widgets::Button::new(restart).ui(ui) {
|
if widgets::Button::new(restart).ui(ui) {
|
||||||
pop = Population::new(
|
pop = Population::new(
|
||||||
size as usize,
|
size as usize,
|
||||||
|
auto_switch,
|
||||||
hlayers.clone(),
|
hlayers.clone(),
|
||||||
mut_rate,
|
mut_rate,
|
||||||
activs[activ],
|
activs[activ],
|
||||||
|
@ -371,9 +401,60 @@ async fn main() {
|
||||||
hash!(),
|
hash!(),
|
||||||
vec2(ui_width * 0.2, ui_height * 0.8 - 2. * th - 2. * ui_thick),
|
vec2(ui_width * 0.2, ui_height * 0.8 - 2. * th - 2. * ui_thick),
|
||||||
)
|
)
|
||||||
.position(vec2(ui_width * 0.8 - th, ui_height * 0.2 + ui_thick + th))
|
.position(vec2(ui_width * 0.6, ui_height * 0.23 + ui_thick + th))
|
||||||
|
.ui(ui, |ui| {
|
||||||
|
ui.label(None, "Track Ship:");
|
||||||
|
|
||||||
|
if ui.button(None, "Best Alive") {
|
||||||
|
pop.track_best(false);
|
||||||
|
}
|
||||||
|
if ui.button(None, "Current #1") {
|
||||||
|
pop.track_best(true);
|
||||||
|
}
|
||||||
|
if ui.button(None, "LastGen #1") {
|
||||||
|
pop.track_prev_best();
|
||||||
|
}
|
||||||
|
ui.label(None, " ");
|
||||||
|
ui.label(None, "Auto Switch");
|
||||||
|
ui.label(None, "When Dead to:");
|
||||||
|
|
||||||
|
if auto_switch == Some(AutoSwitch::Best) {
|
||||||
|
ui.push_skin(&skin3);
|
||||||
|
ui.button(None, "Current #1");
|
||||||
|
ui.pop_skin();
|
||||||
|
} else {
|
||||||
|
if ui.button(None, "Current #1") {
|
||||||
|
auto_switch = Some(AutoSwitch::Best);
|
||||||
|
pop.auto_switch = auto_switch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if auto_switch == Some(AutoSwitch::BestAlive) {
|
||||||
|
ui.push_skin(&skin3);
|
||||||
|
ui.button(None, "Best Alive");
|
||||||
|
ui.pop_skin();
|
||||||
|
} else {
|
||||||
|
if ui.button(None, "Best Alive") {
|
||||||
|
auto_switch = Some(AutoSwitch::BestAlive);
|
||||||
|
pop.auto_switch = auto_switch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if auto_switch.is_none() {
|
||||||
|
ui.push_skin(&skin3);
|
||||||
|
ui.button(None, "Do Nothing");
|
||||||
|
ui.pop_skin();
|
||||||
|
} else {
|
||||||
|
if ui.button(None, "Do Nothing") {
|
||||||
|
auto_switch = None;
|
||||||
|
pop.auto_switch = auto_switch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
widgets::Group::new(
|
||||||
|
hash!(),
|
||||||
|
vec2(ui_width * 0.2, ui_height * 0.8 - 2. * th - 2. * ui_thick),
|
||||||
|
)
|
||||||
|
.position(vec2(ui_width * 0.8 - th, ui_height * 0.22 + ui_thick + th))
|
||||||
.ui(ui, |ui| {
|
.ui(ui, |ui| {
|
||||||
// ui.input_text(hash!(), "vec2(100., 100.)", &mut xy);
|
|
||||||
ui.label(None, "Hidden Layers");
|
ui.label(None, "Hidden Layers");
|
||||||
ui.label(None, "Neurons Config");
|
ui.label(None, "Neurons Config");
|
||||||
|
|
||||||
|
@ -383,6 +464,7 @@ async fn main() {
|
||||||
if prev_hlayers != hlayers {
|
if prev_hlayers != hlayers {
|
||||||
pop = Population::new(
|
pop = Population::new(
|
||||||
size as usize,
|
size as usize,
|
||||||
|
auto_switch,
|
||||||
hlayers.clone(),
|
hlayers.clone(),
|
||||||
mut_rate,
|
mut_rate,
|
||||||
activs[activ],
|
activs[activ],
|
||||||
|
|
|
@ -6,6 +6,12 @@ use crate::{
|
||||||
HEIGHT, WIDTH,
|
HEIGHT, WIDTH,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
pub enum AutoSwitch {
|
||||||
|
Best,
|
||||||
|
BestAlive,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Population {
|
pub struct Population {
|
||||||
size: usize,
|
size: usize,
|
||||||
|
@ -15,16 +21,24 @@ pub struct Population {
|
||||||
pub worlds: Vec<World>,
|
pub worlds: Vec<World>,
|
||||||
pub track: usize,
|
pub track: usize,
|
||||||
pub hlayers: Vec<usize>,
|
pub hlayers: Vec<usize>,
|
||||||
|
pub auto_switch: Option<AutoSwitch>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Population {
|
impl Population {
|
||||||
pub fn new(size: usize, hlayers: Vec<usize>, mut_rate: f32, activ: ActivationFunc) -> Self {
|
pub fn new(
|
||||||
|
size: usize,
|
||||||
|
auto_switch: Option<AutoSwitch>,
|
||||||
|
hlayers: Vec<usize>,
|
||||||
|
mut_rate: f32,
|
||||||
|
activ: ActivationFunc,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
size,
|
size,
|
||||||
hlayers: hlayers.clone(),
|
hlayers: hlayers.clone(),
|
||||||
worlds: (0..size)
|
worlds: (0..size)
|
||||||
.map(|_| World::new(Some(hlayers.clone()), Some(mut_rate), Some(activ)))
|
.map(|_| World::new(Some(hlayers.clone()), Some(mut_rate), Some(activ)))
|
||||||
.collect(),
|
.collect(),
|
||||||
|
auto_switch,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +51,14 @@ impl Population {
|
||||||
world.update();
|
world.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if self.worlds[self.track].over {
|
||||||
|
if let Some(auto_switch) = self.auto_switch {
|
||||||
|
match auto_switch {
|
||||||
|
AutoSwitch::Best => self.track_best(true),
|
||||||
|
AutoSwitch::BestAlive => self.track_best(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if !alive {
|
if !alive {
|
||||||
self.gen += 1;
|
self.gen += 1;
|
||||||
self.next_gen();
|
self.next_gen();
|
||||||
|
@ -62,6 +84,25 @@ impl Population {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn track_best(&mut self, can_be_dead: bool) {
|
||||||
|
self.worlds[self.track].track(false);
|
||||||
|
let i = self
|
||||||
|
.worlds
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(_, w)| !w.over || can_be_dead)
|
||||||
|
.max_by(|(_, a), (_, b)| a.fitness.total_cmp(&b.fitness))
|
||||||
|
.map(|(i, _)| i);
|
||||||
|
if let Some(i) = i {
|
||||||
|
self.worlds[i].track(true);
|
||||||
|
self.track = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn track_prev_best(&mut self) {
|
||||||
|
self.worlds[self.track].track(false);
|
||||||
|
self.worlds[0].track(true);
|
||||||
|
self.track = 0;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn change_mut(&mut self, mut_rate: f32) {
|
pub fn change_mut(&mut self, mut_rate: f32) {
|
||||||
for world in &mut self.worlds {
|
for world in &mut self.worlds {
|
||||||
|
|
14
src/world.rs
14
src/world.rs
|
@ -181,7 +181,7 @@ impl World {
|
||||||
draw_text_ex(
|
draw_text_ex(
|
||||||
if self.over { "DEAD" } else { "ALIVE" },
|
if self.over { "DEAD" } else { "ALIVE" },
|
||||||
-width * 0.5 + 20.,
|
-width * 0.5 + 20.,
|
||||||
70.,
|
55.,
|
||||||
{
|
{
|
||||||
let mut p = params.clone();
|
let mut p = params.clone();
|
||||||
p.color = if self.over { RED } else { GREEN };
|
p.color = if self.over { RED } else { GREEN };
|
||||||
|
@ -191,19 +191,25 @@ impl World {
|
||||||
draw_text_ex(
|
draw_text_ex(
|
||||||
&format!("Hits: {}", self.score),
|
&format!("Hits: {}", self.score),
|
||||||
-width * 0.5 + 20.,
|
-width * 0.5 + 20.,
|
||||||
90.,
|
75.,
|
||||||
params,
|
params,
|
||||||
);
|
);
|
||||||
draw_text_ex(
|
draw_text_ex(
|
||||||
&format!("Fired: {}", self.player.shots),
|
&format!("Fired: {}", self.player.shots),
|
||||||
-width * 0.5 + 20.,
|
-width * 0.5 + 20.,
|
||||||
110.,
|
95.,
|
||||||
params,
|
params,
|
||||||
);
|
);
|
||||||
draw_text_ex(
|
draw_text_ex(
|
||||||
&format!("Fitness: {:.2}", self.fitness),
|
&format!("Fitness: {:.2}", self.fitness),
|
||||||
-width * 0.5 + 20.,
|
-width * 0.5 + 20.,
|
||||||
130.,
|
115.,
|
||||||
|
params,
|
||||||
|
);
|
||||||
|
draw_text_ex(
|
||||||
|
&format!("Lifetime: {:.2}", self.player.lifespan as f32 / 60.),
|
||||||
|
-width * 0.5 + 20.,
|
||||||
|
135.,
|
||||||
params,
|
params,
|
||||||
);
|
);
|
||||||
let str = &format!("RANK #{}", rank);
|
let str = &format!("RANK #{}", rank);
|
||||||
|
|
Loading…
Reference in New Issue