play as human
This commit is contained in:
parent
0796eda239
commit
4fae04f5cd
|
@ -1 +1 @@
|
||||||
{"config":[6,7,7,4],"weights":[[[-0.5567123,0.23674688,-0.8115287,0.73920447,-0.9627226,0.98842543,-0.08672536,0.11889564,0.19367097,0.84720945,0.10916865,0.19691469,0.34381783,-1.1452736,-0.7501932,0.65345323,1.1373248,-0.2888124,0.288057,0.09440576,-0.061547264,0.35609803,0.14600815,0.4276784,-0.8315937,-0.5220405,-0.7070066,-0.41821334,0.88325745,1.179611,-0.38369912,0.8185778,0.1276589,0.11540664,-0.2861217,-0.88901085],6,6],[[0.64678603,0.11032932,-0.17325084,0.4482577,-0.4668608,-0.061782226,-0.23166645,-1.189321,0.38457078,-0.040191226,-1.0519018,0.53179306,-0.27904406,0.18169245,-0.028529042,0.4248598,0.6224678,-0.48197106,-0.8517104,0.626093,-0.53116995,0.74109083,-0.4775906,-0.6105986,-0.11459249,0.54738194,0.53385884,0.05052872,0.56253725,0.6168962,0.3087382,1.4871372,-0.058942188,-0.13154379,0.6763109,-0.72106224,-0.13756883,-0.10921177,-0.12797734,-0.12984648,0.47288033,0.06618643],6,7],[[0.24218078,0.1842654,0.27074534,0.50006706,0.9494213,-0.7030016,-0.1101043,0.5054117,0.18234585,-1.429309,-0.14925024,0.47471818,-1.079322,1.0112062,-0.5279594,-0.13144909,1.0667706,-0.85650563,0.076754875,1.3830073,-0.50329316,0.61952496,-0.94159657,-0.27969155,-0.6343474,0.08405438,1.0401202,-1.3237122],4,7]],"activ_func":"ReLU","mut_rate":0.05}
|
{"config":[6,7,7,4],"weights":[[[0.35300237,0.4247243,-0.7875665,-1.6072044,1.5638344,1.0116522,0.91539335,0.72748256,0.10979596,0.916985,1.1620126,-0.879529,-0.008039723,-1.4823594,-0.7815808,-0.9131131,0.25484133,-0.8343034,-0.97603,0.5233137,-0.8282123,-0.20260507,0.8145971,0.688537,1.0713704,0.8801996,2.5356312,0.14526872,0.2973215,-1.1754538,0.007596435,0.3534879,-0.29665652,1.1665709,-1.9667246,-1.3233892],6,6],[[-0.52504927,1.3216119,1.0895479,0.84873104,0.64963293,-2.0617585,-0.24353297,2.0812314,-0.06842113,-1.2582295,2.5253322,-0.04738267,-0.14587633,0.37131867,-0.18781468,-2.2502813,2.5478582,0.04243115,1.1420923,0.5919767,0.5798261,0.43632478,0.5544543,0.14799483,-1.3338035,-0.23948197,0.9541234,0.7938923,0.30592227,-0.044575863,-1.4038266,-1.282537,0.9133283,-0.09069362,-1.2081418,-0.05495484,1.632303,1.0032419,1.1147637,0.46290535,-0.035745874,-1.9028112],6,7],[[-0.16735676,-0.28051043,-1.0052958,0.33411616,2.1245909,-0.4129878,1.1603845,1.0717844,-0.6117815,-0.6603155,0.82145613,-0.6706493,1.7019055,-1.4384344,-1.4858634,-0.5874535,1.6686711,0.2978619,-0.46680036,-0.41379213,-1.1143796,0.6741852,-0.6568759,0.20075007,0.050768528,-0.39008367,0.6281415,2.8667881],4,7]],"activ_func":"ReLU","mut_rate":0.05}
|
111
src/main.rs
111
src/main.rs
|
@ -61,7 +61,9 @@ async fn main() {
|
||||||
let mut speedup = 1;
|
let mut speedup = 1;
|
||||||
let mut paused = false;
|
let mut paused = false;
|
||||||
let mut bias = false;
|
let mut bias = false;
|
||||||
|
let mut human = false;
|
||||||
let mut size: u32 = 100;
|
let mut size: u32 = 100;
|
||||||
|
let mut world: World = World::new(None, None, None);
|
||||||
|
|
||||||
let mut hlayers: Vec<usize> = vec![6, 6, 0];
|
let mut hlayers: Vec<usize> = vec![6, 6, 0];
|
||||||
let mut prev_hlayers = hlayers.clone();
|
let mut prev_hlayers = hlayers.clone();
|
||||||
|
@ -76,7 +78,7 @@ async fn main() {
|
||||||
ActivationFunc::Sigmoid,
|
ActivationFunc::Sigmoid,
|
||||||
ActivationFunc::Tanh,
|
ActivationFunc::Tanh,
|
||||||
];
|
];
|
||||||
let mut auto_switch = Some(AutoSwitch::Best);
|
let mut auto_switch = Some(AutoSwitch::BestAlive);
|
||||||
|
|
||||||
let mut pop = Population::new(
|
let mut pop = Population::new(
|
||||||
size as usize,
|
size as usize,
|
||||||
|
@ -241,10 +243,19 @@ async fn main() {
|
||||||
}
|
}
|
||||||
if !paused {
|
if !paused {
|
||||||
for _ in 0..speedup {
|
for _ in 0..speedup {
|
||||||
pop.update();
|
if !human {
|
||||||
|
pop.update()
|
||||||
|
} else if !world.over {
|
||||||
|
world.update()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if human {
|
||||||
|
world.draw(pop.debug);
|
||||||
|
pop.draw_borders();
|
||||||
|
} else {
|
||||||
pop.draw();
|
pop.draw();
|
||||||
|
}
|
||||||
draw_rectangle_lines(-WIDTH * 0.5, -HEIGHT * 0.5, WIDTH, HEIGHT, 2., WHITE);
|
draw_rectangle_lines(-WIDTH * 0.5, -HEIGHT * 0.5, WIDTH, HEIGHT, 2., WHITE);
|
||||||
draw_rectangle_lines(
|
draw_rectangle_lines(
|
||||||
WIDTH * 0.5 + th,
|
WIDTH * 0.5 + th,
|
||||||
|
@ -270,7 +281,12 @@ async fn main() {
|
||||||
bias,
|
bias,
|
||||||
);
|
);
|
||||||
set_camera(&statcam);
|
set_camera(&statcam);
|
||||||
pop.worlds[pop.track].draw_stats(
|
let w = if human {
|
||||||
|
&world
|
||||||
|
} else {
|
||||||
|
&pop.worlds[pop.track]
|
||||||
|
};
|
||||||
|
w.draw_stats(
|
||||||
screen_width() - WIDTH - 3. * th,
|
screen_width() - WIDTH - 3. * th,
|
||||||
(screen_height() - 7. * th) * 0.5 - 2. * ui_thick,
|
(screen_height() - 7. * th) * 0.5 - 2. * ui_thick,
|
||||||
pop.worlds.iter().fold(1, |acc, w| {
|
pop.worlds.iter().fold(1, |acc, w| {
|
||||||
|
@ -387,6 +403,9 @@ async fn main() {
|
||||||
};
|
};
|
||||||
ui.same_line(0.);
|
ui.same_line(0.);
|
||||||
if widgets::Button::new(restart).ui(ui) {
|
if widgets::Button::new(restart).ui(ui) {
|
||||||
|
if human {
|
||||||
|
world = World::new(None, None, None);
|
||||||
|
} else {
|
||||||
pop = Population::new(
|
pop = Population::new(
|
||||||
size as usize,
|
size as usize,
|
||||||
auto_switch,
|
auto_switch,
|
||||||
|
@ -394,40 +413,37 @@ async fn main() {
|
||||||
mut_rate,
|
mut_rate,
|
||||||
activs[activ],
|
activs[activ],
|
||||||
);
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
ui.push_skin(&skin2);
|
ui.push_skin(&skin2);
|
||||||
widgets::Group::new(
|
widgets::Group::new(
|
||||||
hash!(),
|
hash!(),
|
||||||
vec2(ui_width * 0.2, ui_height * 0.8 - 2. * th - 2. * ui_thick),
|
vec2(ui_width * 0.2, ui_height * 0.85 - 2. * th - 2. * ui_thick),
|
||||||
)
|
)
|
||||||
.position(vec2(ui_width * 0.6, ui_height * 0.23 + ui_thick + th))
|
.position(vec2(ui_width * 0.82, ui_height * 0.15 + ui_thick + th))
|
||||||
.ui(ui, |ui| {
|
.ui(ui, |ui| {
|
||||||
ui.label(None, "Track Ship:");
|
ui.label(None, "Track Ship:");
|
||||||
|
ui.label(None, "(or click a");
|
||||||
|
ui.label(None, "ship in game)");
|
||||||
|
|
||||||
if ui.button(None, "Best Alive") {
|
if ui.button(None, "Best Alive") {
|
||||||
pop.track_best(false);
|
pop.track_best(false);
|
||||||
}
|
}
|
||||||
if ui.button(None, "Current #1") {
|
if ui.button(None, "Current #1") {
|
||||||
pop.track_best(true);
|
pop.track_best(true);
|
||||||
|
auto_switch = Some(AutoSwitch::Best);
|
||||||
|
pop.auto_switch = auto_switch;
|
||||||
}
|
}
|
||||||
if ui.button(None, "LastGen #1") {
|
if ui.button(None, "LastGen #1") {
|
||||||
pop.track_prev_best();
|
pop.track_prev_best();
|
||||||
|
auto_switch = None;
|
||||||
|
pop.auto_switch = auto_switch;
|
||||||
}
|
}
|
||||||
ui.label(None, " ");
|
ui.label(None, " ");
|
||||||
ui.label(None, "Auto Switch");
|
ui.label(None, "Auto Switch");
|
||||||
ui.label(None, "When Dead to:");
|
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) {
|
if auto_switch == Some(AutoSwitch::BestAlive) {
|
||||||
ui.push_skin(&skin3);
|
ui.push_skin(&skin3);
|
||||||
ui.button(None, "Best Alive");
|
ui.button(None, "Best Alive");
|
||||||
|
@ -438,6 +454,16 @@ async fn main() {
|
||||||
pop.auto_switch = auto_switch;
|
pop.auto_switch = auto_switch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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.is_none() {
|
if auto_switch.is_none() {
|
||||||
ui.push_skin(&skin3);
|
ui.push_skin(&skin3);
|
||||||
ui.button(None, "Do Nothing");
|
ui.button(None, "Do Nothing");
|
||||||
|
@ -451,10 +477,47 @@ async fn main() {
|
||||||
});
|
});
|
||||||
widgets::Group::new(
|
widgets::Group::new(
|
||||||
hash!(),
|
hash!(),
|
||||||
vec2(ui_width * 0.2, ui_height * 0.8 - 2. * th - 2. * ui_thick),
|
vec2(ui_width * 0.2, ui_height * 0.85 - 2. * th - 2. * ui_thick),
|
||||||
)
|
)
|
||||||
.position(vec2(ui_width * 0.8 - th, ui_height * 0.22 + ui_thick + th))
|
.position(vec2(ui_width * 0.6 - th, ui_height * 0.15 + ui_thick + th))
|
||||||
.ui(ui, |ui| {
|
.ui(ui, |ui| {
|
||||||
|
ui.label(None, " ");
|
||||||
|
ui.push_skin(&skin);
|
||||||
|
if ui.button(
|
||||||
|
None,
|
||||||
|
if human {
|
||||||
|
" Train AI "
|
||||||
|
} else {
|
||||||
|
"Play As Human"
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
human = !human;
|
||||||
|
if human {
|
||||||
|
world = World::new(None, None, None);
|
||||||
|
} else {
|
||||||
|
pop = Population::new(
|
||||||
|
size as usize,
|
||||||
|
auto_switch,
|
||||||
|
hlayers.clone(),
|
||||||
|
mut_rate,
|
||||||
|
activs[activ],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui.pop_skin();
|
||||||
|
ui.label(None, "Mutation Rate");
|
||||||
|
ui.drag(hash!(), "«Drag»", Some((0., 1.)), &mut mut_rate);
|
||||||
|
if prev_mut_rate != mut_rate {
|
||||||
|
pop.change_mut(mut_rate);
|
||||||
|
prev_mut_rate = mut_rate;
|
||||||
|
}
|
||||||
|
ui.label(None, "Activation Func");
|
||||||
|
ui.combo_box(hash!(), "«Select»", &["ReLU", "Sigm", "Tanh"], &mut activ);
|
||||||
|
if prev_activ != activ {
|
||||||
|
pop.change_activ(activs[activ]);
|
||||||
|
prev_activ = activ;
|
||||||
|
}
|
||||||
|
ui.label(None, " ");
|
||||||
ui.label(None, "Hidden Layers");
|
ui.label(None, "Hidden Layers");
|
||||||
ui.label(None, "Neurons Config");
|
ui.label(None, "Neurons Config");
|
||||||
|
|
||||||
|
@ -471,20 +534,6 @@ async fn main() {
|
||||||
);
|
);
|
||||||
prev_hlayers = hlayers.clone();
|
prev_hlayers = hlayers.clone();
|
||||||
}
|
}
|
||||||
ui.label(None, " ");
|
|
||||||
ui.label(None, "Mutation Rate");
|
|
||||||
ui.drag(hash!(), "«Drag»", Some((0., 1.)), &mut mut_rate);
|
|
||||||
if prev_mut_rate != mut_rate {
|
|
||||||
pop.change_mut(mut_rate);
|
|
||||||
prev_mut_rate = mut_rate;
|
|
||||||
}
|
|
||||||
ui.label(None, " ");
|
|
||||||
ui.label(None, "Activation Func");
|
|
||||||
ui.combo_box(hash!(), "«Select»", &["ReLU", "Sigm", "Tanh"], &mut activ);
|
|
||||||
if prev_activ != activ {
|
|
||||||
pop.change_activ(activs[activ]);
|
|
||||||
prev_activ = activ;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
ui.pop_skin();
|
ui.pop_skin();
|
||||||
},
|
},
|
||||||
|
|
|
@ -96,7 +96,7 @@ impl Player {
|
||||||
// .unwrap();
|
// .unwrap();
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
if asteroid.check_collision(self.pos, 8.) || self.lifespan > 4000 {
|
if asteroid.check_collision(self.pos, 8.) || self.lifespan > 4000 && self.brain.is_some() {
|
||||||
self.alive = false;
|
self.alive = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -157,21 +157,21 @@ impl Player {
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if keys[0] {
|
if keys[0] || self.brain.is_none() && is_key_down(KeyCode::Right) {
|
||||||
// RIGHT
|
// RIGHT
|
||||||
self.rot = (self.rot + 0.1 + TAU as f32) % TAU as f32;
|
self.rot = (self.rot + 0.1 + TAU as f32) % TAU as f32;
|
||||||
self.dir = vec2(self.rot.cos(), self.rot.sin());
|
self.dir = vec2(self.rot.cos(), self.rot.sin());
|
||||||
}
|
}
|
||||||
if keys[1] {
|
if keys[1] || self.brain.is_none() && is_key_down(KeyCode::Left) {
|
||||||
// LEFT
|
// LEFT
|
||||||
self.rot = (self.rot - 0.1 + TAU as f32) % TAU as f32;
|
self.rot = (self.rot - 0.1 + TAU as f32) % TAU as f32;
|
||||||
self.dir = vec2(self.rot.cos(), self.rot.sin());
|
self.dir = vec2(self.rot.cos(), self.rot.sin());
|
||||||
}
|
}
|
||||||
if is_key_down(KeyCode::Up) || keys[2] {
|
if keys[2] || self.brain.is_none() && is_key_down(KeyCode::Up) {
|
||||||
// THROTTLE
|
// THROTTLE
|
||||||
self.acc = 0.14;
|
self.acc = 0.14;
|
||||||
}
|
}
|
||||||
if is_key_down(KeyCode::Space) || keys[3] {
|
if keys[3] || self.brain.is_none() && is_key_down(KeyCode::Space) {
|
||||||
if self.last_shot > self.shot_interval {
|
if self.last_shot > self.shot_interval {
|
||||||
self.last_shot = 0;
|
self.last_shot = 0;
|
||||||
self.shots += 1;
|
self.shots += 1;
|
||||||
|
|
|
@ -32,15 +32,18 @@ impl Population {
|
||||||
mut_rate: f32,
|
mut_rate: f32,
|
||||||
activ: ActivationFunc,
|
activ: ActivationFunc,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
let mut s = 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,
|
auto_switch,
|
||||||
|
focus: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
};
|
||||||
|
s.worlds[0].track(true);
|
||||||
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self) {
|
pub fn update(&mut self) {
|
||||||
|
@ -126,8 +129,10 @@ impl Population {
|
||||||
world.draw(self.debug);
|
world.draw(self.debug);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.draw_borders();
|
||||||
|
}
|
||||||
|
|
||||||
// draw black background outside the screen
|
pub fn draw_borders(&self) {
|
||||||
let th = (screen_height() - HEIGHT) * 0.5;
|
let th = (screen_height() - HEIGHT) * 0.5;
|
||||||
draw_rectangle(-WIDTH * 0.5, -screen_height() * 0.5, WIDTH, th, BLACK);
|
draw_rectangle(-WIDTH * 0.5, -screen_height() * 0.5, WIDTH, th, BLACK);
|
||||||
draw_rectangle(-WIDTH * 0.5, screen_height() * 0.5 - th, WIDTH, th, BLACK);
|
draw_rectangle(-WIDTH * 0.5, screen_height() * 0.5 - th, WIDTH, th, BLACK);
|
||||||
|
|
|
@ -23,6 +23,7 @@ impl World {
|
||||||
activ: Option<ActivationFunc>,
|
activ: Option<ActivationFunc>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
color: Color::new(1., 1., 1., if hlayers.is_none() { 0.8 } else { 0.4 }),
|
||||||
player: Player::new(hlayers, mut_rate, activ),
|
player: Player::new(hlayers, mut_rate, activ),
|
||||||
score: 1.,
|
score: 1.,
|
||||||
asteroids: vec![
|
asteroids: vec![
|
||||||
|
@ -32,13 +33,13 @@ impl World {
|
||||||
Asteroid::new(AsteroidSize::Large),
|
Asteroid::new(AsteroidSize::Large),
|
||||||
Asteroid::new(AsteroidSize::Large),
|
Asteroid::new(AsteroidSize::Large),
|
||||||
],
|
],
|
||||||
color: Color::new(1., 1., 1., 0.4),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn simulate(brain: NN) -> Self {
|
pub fn simulate(brain: NN) -> Self {
|
||||||
let mut w = World::new(None, None, None);
|
let mut w = World::new(None, None, None);
|
||||||
w.player.brain = Some(brain);
|
w.player.brain = Some(brain);
|
||||||
|
w.color = Color::new(1., 1., 1., 0.4);
|
||||||
w
|
w
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue