xxxxxxxxxx
338
var population;
var lifespan = 300;
var popsize = 40;
var count = 0;
var lifeG;
var generation = 1;
var dead = 0;
var win = 0;
var prevwin = 0;
var bestwin = 0;
var target;
var maxForce = 0.4;
let prevbestdna = new DNA();
let winnerdna = [];
var maxwinnerarr = 2000;
var usersettings;
let lifespanslider;
var userlifespan = 300;
let popsizeslider;
var userpopsize = 40;
let restartbutton;
var rx = 100;
var ry = 150;
var rw = 200;
var rh = 10;
var cx = 150;
var cy = 260;
let bactImg;
var bactsize = 25;
let cellImg;
var cellsize = 30;
function preload() {
bactImg = loadImage("Bacteria.png");
cellImg = loadImage("cell.png");
}
function setup() {
createCanvas(400, 300);
population = new Population();
lifeG = createP();
target = createVector(width / 2, 50);
lifespanslider = createSlider(1, 1000, 300, 1);
popsizeslider = createSlider(1, 800, 40, 1);
restartbutton = createButton("Apply");
restartbutton.mousePressed(restartsim);
usersettings = createP();
}
function restartsim(){
lifespan = userlifespan;
popsize = userpopsize;
population = new Population();
count = 0;
generation = 1;
dead = 0;
win = 0;
prevwin = 0;
bestwin = 0;
prevbestdna = new DNA();
}
function draw() {
background(0);
population.run();
lifeG.html(
"Generation: " +
generation +
" | Ticks: " +
count +
"/" +
lifespan +
" | Previous Win: " +
prevwin +
" | Best: " +
bestwin +
" | Dead: " +
dead
);
userlifespan = lifespanslider.value();
userpopsize = popsizeslider.value();
usersettings.html("Lifespan: " + userlifespan + " | Population: " + userpopsize);
count++;
if (count == lifespan || dead == popsize) {
population.evaluate();
population.selection();
count = 0;
generation++;
prevwin = win;
if (win > bestwin) {
bestwin = win;
}
win = 0;
dead = 0;
}
if (generation == 60 && prevwin == 0) {
generation = 0;
population = new Population();
win = 0;
dead = 0;
}
fill(255, 0, 0);
rect(rx, ry, rw, rh);
fill(0, 255, 0);
ellipse(target.x, target.y, 16, 16);
imageMode(CENTER);
image(cellImg, target.x, target.y, cellsize, cellsize);
}
function Population() {
this.rockets = [];
this.popsize = popsize;
this.matingpool = [];
for (var i = 0; i < this.popsize; i++) {
this.rockets[i] = new Rocket();
}
this.evaluate = function () {
var maxfit = 0;
var minfit = 9999;
for (var i = 0; i < this.popsize; i++) {
//calculate fitness
this.rockets[i].calcFitness();
if (this.rockets[i].fitness > maxfit) {
//max fitness
maxfit = this.rockets[i].fitness;
}
if (this.rockets[i].fitness < minfit) {
//minimum fitness
minfit = this.rockets[i].fitness;
}
}
for (i = 0; i < this.popsize; i++) {
//update worst rocket with best previous dna
if (this.rockets[i].fitness == minfit) {
this.rockets[i].dna = prevbestdna;
this.rockets[i].fitness = maxfit - 10;
}
}
for (i = 0; i < this.popsize; i++) {
//save best dna from flight
if (this.rockets[i].fitness == maxfit) {
prevbestdna = this.rockets[i].dna;
}
this.rockets[i].fitness /= maxfit;
}
this.matingpool = [];
for (i = 0; i < this.popsize; i++) {
var n = this.rockets[i].fitness * 100;
for (var j = 0; j < n; j++) {
this.matingpool.push(this.rockets[i]);
}
}
for (i = 0; i < winnerdna; i++){
for (var j = 0; j < 50; j++){
this.matingpool.push(winnerdna[i]);
}
}
}
this.selection = function () {
var newRockets = [];
for (var i = 0; i < this.rockets.length; i++) {
var parentA = random(this.matingpool).dna;
var parentB = random(this.matingpool).dna;
var child = parentA.crossover(parentB);
child.mutation();
newRockets[i] = new Rocket(child);
}
this.rockets = newRockets;
};
this.run = function () {
for (var i = 0; i < this.popsize; i++) {
this.rockets[i].update();
this.rockets[i].show();
}
};
}
function DNA(genes) {
if (genes) {
this.genes = genes;
} else {
this.genes = [];
for (var i = 0; i < lifespan; i++) {
this.genes[i] = p5.Vector.random2D();
this.genes[i].setMag(maxForce);
}
}
this.crossover = function (partner) {
var newgenes = [];
var mid = floor(random(this.genes.length));
for (var i = 0; i < this.genes.length; i++) {
if (i > mid) {
newgenes[i] = this.genes[i];
} else {
newgenes[i] = partner.genes[i];
}
}
return new DNA(newgenes);
};
this.mutation = function () {
for (var i = 0; i < this.genes.length; i++) {
if (random(1) < 0.01) {
this.genes[i] = p5.Vector.random2D();
this.genes[i].setMag(maxForce);
}
}
};
}
function Rocket(dna) {
this.pos = createVector(cx, cy);
this.vel = createVector();
this.acc = createVector();
this.completed = false;
this.crashed = false;
this.wallcrash = false;
this.groundcrash = false;
this.barriercrash = false;
this.compTime = 0;
this.crashTime = 0;
this.closest = 9999;
if (dna) {
this.dna = dna;
} else {
this.dna = new DNA();
}
this.fitness = 0;
this.applyForce = function (force) {
this.acc.add(force);
};
this.calcFitness = function () {
var d = dist(this.pos.x, this.pos.y, target.x, target.y);
this.closest = map(this.closest, 0, width, width, 0);
this.fitness =
map(d, 0, width, width, 0) +
this.closest +
this.compTime +
this.crashTime;
if (this.completed) {
this.fitness *= 10;
}
if (this.crashed) {
if (this.wallcrash) {
this.fitness /= 1.5;
}
if (this.barriercrash) {
this.fitness /= 1.5;
}
if (this.groundcrash) {
this.fitenss /= 2;
}
}
};
this.update = function () {
var d = dist(this.pos.x, this.pos.y, target.x, target.y);
if (d < this.closest) {
this.closest = d;
}
if (d < 15 && !this.completed) {
this.completed = true;
this.pos = target.copy();
this.compTime = map(count, 0, lifespan, 400, 0);
if (winnerdna.length > maxwinnerarr){
winnerdna.shift();
}
winnerdna.push(this.dna);
dead++;
win++;
}
if (!this.crashed) {
if (
this.pos.x > rx &&
this.pos.x < rx + rw &&
this.pos.y > ry &&
this.pos.y < ry + rh
) {
this.crashed = true;
this.barriercrash = true;
dead++;
this.crashTime = map(count, 0, lifespan, 100, 0);
}
if (this.pos.x < 0 || this.pos.x > width || this.pos.y < -100) {
this.crashed = true;
this.wallcrash = true;
dead++;
this.crashTime = map(count, 0, lifespan, 100, 0);
}
if (this.pos.y > height + 5) {
this.crashed = true;
this.groundcrash = true;
dead++;
this.crashTime = map(count, 0, lifespan, 100, 0);
}
}
this.applyForce(this.dna.genes[count]);
if (!this.completed && !this.crashed) {
this.vel.add(this.acc);
this.pos.add(this.vel);
this.acc.mult(0);
this.vel.limit(4);
}
};
this.show = function () {
push();
noStroke();
fill(255, 150);
translate(this.pos.x, this.pos.y);
rotate(3.93 + this.vel.heading());
imageMode(CENTER);
image(bactImg, 0, 0, bactsize, bactsize);
pop();
};
}