From d646875e2dcb8ef9eb77e62d2f85ce358b012709 Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Tue, 14 Apr 2020 09:09:59 +0400 Subject: [PATCH 1/3] removed box2D as a dependancy --- index.html | 1 - 1 file changed, 1 deletion(-) diff --git a/index.html b/index.html index 3a80141..c82c71d 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,6 @@ - From fdcc3d797f2cb2a819e01e9be2c86068869996e2 Mon Sep 17 00:00:00 2001 From: Ryan Boldi Date: Tue, 14 Apr 2020 09:10:09 +0400 Subject: [PATCH 2/3] spelling mistake --- Player.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Player.js b/Player.js index 9f9aa2d..98eb395 100644 --- a/Player.js +++ b/Player.js @@ -84,7 +84,7 @@ class Player { } //--------------------------------------------------------------------------------------------------------------------------------------------------------- - //fot Genetic algorithm + //for Genetic algorithm calculateFitness() { this.fitness = random(10); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Date: Tue, 14 Apr 2020 09:11:28 +0400 Subject: [PATCH 3/3] Changed indentation to make it look nicer and more javascript-y --- GENOME.JS | 166 +++++++++++++++++++++--------------------- Node.js | 80 ++++++++++----------- Player.js | 44 ++++++------ PlayerOld.js | 44 ++++++------ Population.js | 196 +++++++++++++++++++++++++------------------------- Species.js | 114 ++++++++++++++--------------- sketch.js | 66 ++++++++--------- 7 files changed, 355 insertions(+), 355 deletions(-) diff --git a/GENOME.JS b/GENOME.JS index b8d4123..5e6db30 100644 --- a/GENOME.JS +++ b/GENOME.JS @@ -118,23 +118,23 @@ class Genome { //sets up the NN as a list of this.nodes in order to be engaged generateNetwork() { - this.connectNodes(); - this.network = []; - //for each layer add the node in that layer, since layers cannot connect to themselves there is no need to order the this.nodes within a layer - - for (var l = 0; l < this.layers; l++) { //for each layer - for (var i = 0; i < this.nodes.length; i++) { //for each node - if (this.nodes[i].layer == l) { //if that node is in that layer - this.network.push(this.nodes[i]); - } + this.connectNodes(); + this.network = []; + //for each layer add the node in that layer, since layers cannot connect to themselves there is no need to order the this.nodes within a layer + + for (var l = 0; l < this.layers; l++) { //for each layer + for (var i = 0; i < this.nodes.length; i++) { //for each node + if (this.nodes[i].layer == l) { //if that node is in that layer + this.network.push(this.nodes[i]); } } } - //----------------------------------------------------------------------------------------------------------------------------------------- - //mutate the NN by adding a new node - //it does this by picking a random connection and disabling it then 2 new connections are added - //1 between the input node of the disabled connection and the new node - //and the other between the new node and the output of the disabled connection + } + //----------------------------------------------------------------------------------------------------------------------------------------- + //mutate the NN by adding a new node + //it does this by picking a random connection and disabling it then 2 new connections are added + //1 between the input node of the disabled connection and the new node + //and the other between the new node and the output of the disabled connection addNode(innovationHistory) { //pick a random connection to create a node between if (this.genes.length == 0) { @@ -183,37 +183,37 @@ class Genome { //------------------------------------------------------------------------------------------------------------------ //adds a connection between 2 this.nodes which aren't currently connected addConnection(innovationHistory) { - //cannot add a connection to a fully connected network - if (this.fullyConnected()) { - console.log("connection failed"); - return; - } + //cannot add a connection to a fully connected network + if (this.fullyConnected()) { + console.log("connection failed"); + return; + } - //get random this.nodes - var randomNode1 = floor(random(this.nodes.length)); - var randomNode2 = floor(random(this.nodes.length)); - while (this.randomConnectionNodesAreShit(randomNode1, randomNode2)) { //while the random this.nodes are no good - //get new ones - randomNode1 = floor(random(this.nodes.length)); - randomNode2 = floor(random(this.nodes.length)); - } - var temp; - if (this.nodes[randomNode1].layer > this.nodes[randomNode2].layer) { //if the first random node is after the second then switch - temp = randomNode2; - randomNode2 = randomNode1; - randomNode1 = temp; - } + //get random this.nodes + var randomNode1 = floor(random(this.nodes.length)); + var randomNode2 = floor(random(this.nodes.length)); + while (this.randomConnectionNodesAreShit(randomNode1, randomNode2)) { //while the random this.nodes are no good + //get new ones + randomNode1 = floor(random(this.nodes.length)); + randomNode2 = floor(random(this.nodes.length)); + } + var temp; + if (this.nodes[randomNode1].layer > this.nodes[randomNode2].layer) { //if the first random node is after the second then switch + temp = randomNode2; + randomNode2 = randomNode1; + randomNode1 = temp; + } - //get the innovation number of the connection - //this will be a new number if no identical genome has mutated in the same way - var connectionInnovationNumber = this.getInnovationNumber(innovationHistory, this.nodes[randomNode1], this.nodes[randomNode2]); - //add the connection with a random array + //get the innovation number of the connection + //this will be a new number if no identical genome has mutated in the same way + var connectionInnovationNumber = this.getInnovationNumber(innovationHistory, this.nodes[randomNode1], this.nodes[randomNode2]); + //add the connection with a random array - this.genes.push(new connectionGene(this.nodes[randomNode1], this.nodes[randomNode2], random(-1, 1), connectionInnovationNumber)); //changed this so if error here - this.connectNodes(); - } - //------------------------------------------------------------------------------------------------------------------------------------------- + this.genes.push(new connectionGene(this.nodes[randomNode1], this.nodes[randomNode2], random(-1, 1), connectionInnovationNumber)); //changed this so if error here + this.connectNodes(); + } + //------------------------------------------------------------------------------------------------------------------------------------------- randomConnectionNodesAreShit(r1, r2) { if (this.nodes[r1].layer == this.nodes[r2].layer) return true; // if the this.nodes are in the same layer if (this.nodes[r1].isConnectedTo(this.nodes[r2])) return true; //if the this.nodes are already connected @@ -228,29 +228,29 @@ class Genome { //if this mutation has never been seen before then it will be given a new unique innovation number //if this mutation matches a previous mutation then it will be given the same innovation number as the previous one getInnovationNumber(innovationHistory, from, to) { - var isNew = true; - var connectionInnovationNumber = nextConnectionNo; - for (var i = 0; i < innovationHistory.length; i++) { //for each previous mutation - if (innovationHistory[i].matches(this, from, to)) { //if match found - isNew = false; //its not a new mutation - connectionInnovationNumber = innovationHistory[i].innovationNumber; //set the innovation number as the innovation number of the match - break; - } + var isNew = true; + var connectionInnovationNumber = nextConnectionNo; + for (var i = 0; i < innovationHistory.length; i++) { //for each previous mutation + if (innovationHistory[i].matches(this, from, to)) { //if match found + isNew = false; //its not a new mutation + connectionInnovationNumber = innovationHistory[i].innovationNumber; //set the innovation number as the innovation number of the match + break; } + } - if (isNew) { //if the mutation is new then create an arrayList of varegers representing the current state of the genome - var innoNumbers = []; - for (var i = 0; i < this.genes.length; i++) { //set the innovation numbers - innoNumbers.push(this.genes[i].innovationNo); - } - - //then add this mutation to the innovationHistory - innovationHistory.push(new connectionHistory(from.number, to.number, connectionInnovationNumber, innoNumbers)); - nextConnectionNo++; + if (isNew) { //if the mutation is new then create an arrayList of varegers representing the current state of the genome + var innoNumbers = []; + for (var i = 0; i < this.genes.length; i++) { //set the innovation numbers + innoNumbers.push(this.genes[i].innovationNo); } - return connectionInnovationNumber; + + //then add this mutation to the innovationHistory + innovationHistory.push(new connectionHistory(from.number, to.number, connectionInnovationNumber, innoNumbers)); + nextConnectionNo++; } - //---------------------------------------------------------------------------------------------------------------------------------------- + return connectionInnovationNumber; + } + //---------------------------------------------------------------------------------------------------------------------------------------- //returns whether the network is fully connected or not fullyConnected() { @@ -374,15 +374,15 @@ class Genome { //---------------------------------------------------------------------------------------------------------------------------------------- //returns whether or not there is a gene matching the input innovation number in the input genome matchingGene(parent2, innovationNumber) { - for (var i = 0; i < parent2.genes.length; i++) { - if (parent2.genes[i].innovationNo == innovationNumber) { - return i; - } + for (var i = 0; i < parent2.genes.length; i++) { + if (parent2.genes[i].innovationNo == innovationNumber) { + return i; } - return -1; //no matching gene found } - //---------------------------------------------------------------------------------------------------------------------------------------- - //prints out info about the genome to the console + return -1; //no matching gene found + } + //---------------------------------------------------------------------------------------------------------------------------------------- + //prints out info about the genome to the console printGenome() { console.log("Prvar genome layers:" + this.layers); console.log("bias node: " + this.biasNode); @@ -403,27 +403,27 @@ class Genome { //returns a copy of this genome clone() { - var clone = new Genome(this.inputs, this.outputs, true); + var clone = new Genome(this.inputs, this.outputs, true); - for (var i = 0; i < this.nodes.length; i++) { //copy this.nodes - clone.nodes.push(this.nodes[i].clone()); - } + for (var i = 0; i < this.nodes.length; i++) { //copy this.nodes + clone.nodes.push(this.nodes[i].clone()); + } - //copy all the connections so that they connect the clone new this.nodes + //copy all the connections so that they connect the clone new this.nodes - for (var i = 0; i < this.genes.length; i++) { //copy genes - clone.genes.push(this.genes[i].clone(clone.getNode(this.genes[i].fromNode.number), clone.getNode(this.genes[i].toNode.number))); - } + for (var i = 0; i < this.genes.length; i++) { //copy genes + clone.genes.push(this.genes[i].clone(clone.getNode(this.genes[i].fromNode.number), clone.getNode(this.genes[i].toNode.number))); + } - clone.layers = this.layers; - clone.nextNode = this.nextNode; - clone.biasNode = this.biasNode; - clone.connectNodes(); + clone.layers = this.layers; + clone.nextNode = this.nextNode; + clone.biasNode = this.biasNode; + clone.connectNodes(); - return clone; - } - //---------------------------------------------------------------------------------------------------------------------------------------- - //draw the genome on the screen + return clone; + } + //---------------------------------------------------------------------------------------------------------------------------------------- + //draw the genome on the screen drawGenome(startX, startY, w, h) { //i know its ugly but it works (and is not that important) so I'm not going to mess with it var allNodes = []; //new ArrayList>(); diff --git a/Node.js b/Node.js index d2605b3..ae1a731 100644 --- a/Node.js +++ b/Node.js @@ -12,57 +12,57 @@ class Node { //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //the node sends its output to the inputs of the nodes its connected to engage() { - if(this.layer != 0) { //no sigmoid for the inputs and bias - this.outputValue = this.sigmoid(this.inputSum); - } + if (this.layer != 0) { //no sigmoid for the inputs and bias + this.outputValue = this.sigmoid(this.inputSum); + } - for(var i = 0; i < this.outputConnections.length; i++) { //for each connection - if(this.outputConnections[i].enabled) { //dont do shit if not enabled - this.outputConnections[i].toNode.inputSum += this.outputConnections[i].weight * this.outputValue; //add the weighted output to the sum of the inputs of whatever node this node is connected to - } + for (var i = 0; i < this.outputConnections.length; i++) { //for each connection + if (this.outputConnections[i].enabled) { //dont do shit if not enabled + this.outputConnections[i].toNode.inputSum += this.outputConnections[i].weight * this.outputValue; //add the weighted output to the sum of the inputs of whatever node this node is connected to } } - //---------------------------------------------------------------------------------------------------------------------------------------- - //not used - stepFunction(x) { - if(x < 0) { - return 0; - } else { - return 1; - } + } + //---------------------------------------------------------------------------------------------------------------------------------------- + //not used + stepFunction(x) { + if (x < 0) { + return 0; + } else { + return 1; } - //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - //sigmoid activation function + } + //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //sigmoid activation function sigmoid(x) { - return 1.0 / (1.0 + pow(Math.E, -4.9 * x)); //todo check pow - } - //---------------------------------------------------------------------------------------------------------------------------------------------------------- - //returns whether this node connected to the parameter node - //used when adding a new connection + return 1.0 / (1.0 + pow(Math.E, -4.9 * x)); //todo check pow + } + //---------------------------------------------------------------------------------------------------------------------------------------------------------- + //returns whether this node connected to the parameter node + //used when adding a new connection isConnectedTo(node) { - if(node.layer == this.layer) { //nodes in the same this.layer cannot be connected - return false; - } + if (node.layer == this.layer) { //nodes in the same this.layer cannot be connected + return false; + } - //you get it - if(node.layer < this.layer) { - for(var i = 0; i < node.outputConnections.length; i++) { - if(node.outputConnections[i].toNode == this) { - return true; - } + //you get it + if (node.layer < this.layer) { + for (var i = 0; i < node.outputConnections.length; i++) { + if (node.outputConnections[i].toNode == this) { + return true; } - } else { - for(var i = 0; i < this.outputConnections.length; i++) { - if(this.outputConnections[i].toNode == node) { - return true; - } + } + } else { + for (var i = 0; i < this.outputConnections.length; i++) { + if (this.outputConnections[i].toNode == node) { + return true; } } - - return false; } - //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - //returns a copy of this node + + return false; + } + //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //returns a copy of this node clone() { var clone = new Node(this.number); clone.layer = this.layer; diff --git a/Player.js b/Player.js index 98eb395..9435033 100644 --- a/Player.js +++ b/Player.js @@ -19,17 +19,17 @@ class Player { //--------------------------------------------------------------------------------------------------------------------------------------------------------- show() { - //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< max) { - max = this.decision[i]; - maxIndex = i; - } + for (var i = 0; i < this.decision.length; i++) { + if (this.decision[i] > max) { + max = this.decision[i]; + maxIndex = i; } - - //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< max) { - max = this.decision[i]; - maxIndex = i; - } + for (var i = 0; i < this.decision.length; i++) { + if (this.decision[i] > max) { + max = this.decision[i]; + maxIndex = i; } + } - //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< this.globalBestScore) { - this.globalBestScore = this.players[i].score; - } + for (var i = 0; i < this.players.length; i++) { + if (!this.players[i].dead) { + this.players[i].look(); //get inputs for brain + this.players[i].think(); //use outputs from neural network + this.players[i].update(); //move the player according to the outputs from the neural network + if (!showNothing && (!showBest || i == 0)) { + this.players[i].show(); + } + if (this.players[i].score > this.globalBestScore) { + this.globalBestScore = this.players[i].score; } } - } - //------------------------------------------------------------------------------------------------------------------------------------------ - //returns true if all the players are dead sad + + } + //------------------------------------------------------------------------------------------------------------------------------------------ + //returns true if all the players are dead sad done() { - for (var i = 0; i < this.players.length; i++) { - if (!this.players[i].dead) { - return false; - } + for (var i = 0; i < this.players.length; i++) { + if (!this.players[i].dead) { + return false; } - return true; } - //------------------------------------------------------------------------------------------------------------------------------------------ - //sets the best player globally and for thisthis.gen + return true; + } + //------------------------------------------------------------------------------------------------------------------------------------------ + //sets the best player globally and for thisthis.gen setBestPlayer() { var tempBest = this.species[0].players[0]; tempBest.gen = this.gen; @@ -119,87 +119,87 @@ class Population { //------------------------------------------------------------------------------------------------------------------------------------------ //seperate this.players into this.species based on how similar they are to the leaders of each this.species in the previousthis.gen speciate() { - for (var s of this.species) { //empty this.species - s.players = []; - } - for (var i = 0; i < this.players.length; i++) { //for each player - var speciesFound = false; - for (var s of this.species) { //for each this.species - if (s.sameSpecies(this.players[i].brain)) { //if the player is similar enough to be considered in the same this.species - s.addToSpecies(this.players[i]); //add it to the this.species - speciesFound = true; - break; - } - } - if (!speciesFound) { //if no this.species was similar enough then add a new this.species with this as its champion - this.species.push(new Species(this.players[i])); + for (var s of this.species) { //empty this.species + s.players = []; + } + for (var i = 0; i < this.players.length; i++) { //for each player + var speciesFound = false; + for (var s of this.species) { //for each this.species + if (s.sameSpecies(this.players[i].brain)) { //if the player is similar enough to be considered in the same this.species + s.addToSpecies(this.players[i]); //add it to the this.species + speciesFound = true; + break; } } + if (!speciesFound) { //if no this.species was similar enough then add a new this.species with this as its champion + this.species.push(new Species(this.players[i])); + } } - //------------------------------------------------------------------------------------------------------------------------------------------ - //calculates the fitness of all of the players + } + //------------------------------------------------------------------------------------------------------------------------------------------ + //calculates the fitness of all of the players calculateFitness() { - for (var i = 1; i < this.players.length; i++) { - this.players[i].calculateFitness(); - } + for (var i = 1; i < this.players.length; i++) { + this.players[i].calculateFitness(); } - //------------------------------------------------------------------------------------------------------------------------------------------ - //sorts the players within a this.species and the this.species by their fitnesses + } + //------------------------------------------------------------------------------------------------------------------------------------------ + //sorts the players within a this.species and the this.species by their fitnesses sortSpecies() { - //sort the players within a this.species - for (var s of this.species) { - s.sortSpecies(); - } + //sort the players within a this.species + for (var s of this.species) { + s.sortSpecies(); + } - //sort the this.species by the fitness of its best player - //using selection sort like a loser - var temp = []; //new ArrayList(); - for (var i = 0; i < this.species.length; i++) { - var max = 0; - var maxIndex = 0; - for (var j = 0; j < this.species.length; j++) { - if (this.species[j].bestFitness > max) { - max = this.species[j].bestFitness; - maxIndex = j; - } + //sort the this.species by the fitness of its best player + //using selection sort like a loser + var temp = []; //new ArrayList(); + for (var i = 0; i < this.species.length; i++) { + var max = 0; + var maxIndex = 0; + for (var j = 0; j < this.species.length; j++) { + if (this.species[j].bestFitness > max) { + max = this.species[j].bestFitness; + maxIndex = j; } - temp.push(this.species[maxIndex]); - this.species.splice(maxIndex, 1); - // this.species.remove(maxIndex); - i--; } - this.species = []; - arrayCopy(temp, this.species); - + temp.push(this.species[maxIndex]); + this.species.splice(maxIndex, 1); + // this.species.remove(maxIndex); + i--; } - //------------------------------------------------------------------------------------------------------------------------------------------ - //kills all this.species which haven't improved in 15this.generations + this.species = []; + arrayCopy(temp, this.species); + + } + //------------------------------------------------------------------------------------------------------------------------------------------ + //kills all this.species which haven't improved in 15this.generations killStaleSpecies() { - for (var i = 2; i < this.species.length; i++) { - if (this.species[i].staleness >= 15) { - // .remove(i); - // splice(this.species, i) - this.species.splice(i, 1); - i--; - } + for (var i = 2; i < this.species.length; i++) { + if (this.species[i].staleness >= 15) { + // .remove(i); + // splice(this.species, i) + this.species.splice(i, 1); + i--; } } - //------------------------------------------------------------------------------------------------------------------------------------------ - //if a this.species sucks so much that it wont even be allocated 1 child for the nextthis.generation then kill it now + } + //------------------------------------------------------------------------------------------------------------------------------------------ + //if a this.species sucks so much that it wont even be allocated 1 child for the nextthis.generation then kill it now killBadSpecies() { - var averageSum = this.getAvgFitnessSum(); + var averageSum = this.getAvgFitnessSum(); - for (var i = 1; i < this.species.length; i++) { - if (this.species[i].averageFitness / averageSum * this.players.length < 1) { //if wont be given a single child - // this.species.remove(i); //sad - this.species.splice(i, 1); + for (var i = 1; i < this.species.length; i++) { + if (this.species[i].averageFitness / averageSum * this.players.length < 1) { //if wont be given a single child + // this.species.remove(i); //sad + this.species.splice(i, 1); - i--; - } + i--; } } - //------------------------------------------------------------------------------------------------------------------------------------------ - //returns the sum of each this.species average fitness + } + //------------------------------------------------------------------------------------------------------------------------------------------ + //returns the sum of each this.species average fitness getAvgFitnessSum() { var averageSum = 0; for (var s of this.species) { @@ -220,17 +220,17 @@ class Population { massExtinction() { - for (var i = 5; i < this.species.length; i++) { - // this.species.remove(i); //sad - this.species.splice(i, 1); + for (var i = 5; i < this.species.length; i++) { + // this.species.remove(i); //sad + this.species.splice(i, 1); - i--; - } + i--; } - //------------------------------------------------------------------------------------------------------------------------------------------ - // BATCH LEARNING - //------------------------------------------------------------------------------------------------------------------------------------------ - //update all the players which are alive + } + //------------------------------------------------------------------------------------------------------------------------------------------ + // BATCH LEARNING + //------------------------------------------------------------------------------------------------------------------------------------------ + //update all the players which are alive updateAliveInBatches() { let aliveCount = 0; for (var i = 0; i < this.players.length; i++) { @@ -271,12 +271,12 @@ class Population { } stepWorldsInBatch() { - for (var i = this.batchNo * this.worldsPerBatch; i < min((this.batchNo + 1) * this.worldsPerBatch, worlds.length); i++) { - worlds[i].Step(1 / 30, 10, 10); - } + for (var i = this.batchNo * this.worldsPerBatch; i < min((this.batchNo + 1) * this.worldsPerBatch, worlds.length); i++) { + worlds[i].Step(1 / 30, 10, 10); } - //------------------------------------------------------------------------------------------------------------------------------------------ - //returns true if all the players in a batch are dead sad + } + //------------------------------------------------------------------------------------------------------------------------------------------ + //returns true if all the players in a batch are dead sad batchDead() { for (var i = this.batchNo * this.playersPerBatch; i < min((this.batchNo + 1) * this.playersPerBatch, this.players.length); i++) { if (!this.players[i].dead) { diff --git a/Species.js b/Species.js index 263ed4a..56cebf9 100644 --- a/Species.js +++ b/Species.js @@ -49,43 +49,43 @@ class Species { //returns the number of excess and disjoint genes between the 2 input genomes //i.e. returns the number of genes which dont match getExcessDisjoint(brain1, brain2) { - var matching = 0.0; - for (var i = 0; i < brain1.genes.length; i++) { - for (var j = 0; j < brain2.genes.length; j++) { - if (brain1.genes[i].innovationNo == brain2.genes[j].innovationNo) { - matching++; - break; - } + var matching = 0.0; + for (var i = 0; i < brain1.genes.length; i++) { + for (var j = 0; j < brain2.genes.length; j++) { + if (brain1.genes[i].innovationNo == brain2.genes[j].innovationNo) { + matching++; + break; } } - return (brain1.genes.length + brain2.genes.length - 2 * (matching)); //return no of excess and disjoint genes } - //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - //returns the avereage weight difference between matching genes in the input genomes + return (brain1.genes.length + brain2.genes.length - 2 * (matching)); //return no of excess and disjoint genes + } + //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + //returns the avereage weight difference between matching genes in the input genomes averageWeightDiff(brain1, brain2) { - if (brain1.genes.length == 0 || brain2.genes.length == 0) { - return 0; - } + if (brain1.genes.length == 0 || brain2.genes.length == 0) { + return 0; + } - var matching = 0; - var totalDiff = 0; - for (var i = 0; i < brain1.genes.length; i++) { - for (var j = 0; j < brain2.genes.length; j++) { - if (brain1.genes[i].innovationNo == brain2.genes[j].innovationNo) { - matching++; - totalDiff += abs(brain1.genes[i].weight - brain2.genes[j].weight); - break; - } + var matching = 0; + var totalDiff = 0; + for (var i = 0; i < brain1.genes.length; i++) { + for (var j = 0; j < brain2.genes.length; j++) { + if (brain1.genes[i].innovationNo == brain2.genes[j].innovationNo) { + matching++; + totalDiff += abs(brain1.genes[i].weight - brain2.genes[j].weight); + break; } } - if (matching == 0) { //divide by 0 error - return 100; - } - return totalDiff / matching; } - //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - //sorts the species by fitness + if (matching == 0) { //divide by 0 error + return 100; + } + return totalDiff / matching; + } + //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + //sorts the species by fitness sortSpecies() { var temp = []; // new ArrayList < Player > (); @@ -127,13 +127,13 @@ class Species { //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //simple stuff setAverage() { - var sum = 0; - for (var i = 0; i < this.players.length; i++) { - sum += this.players[i].fitness; - } - this.averageFitness = sum / this.players.length; + var sum = 0; + for (var i = 0; i < this.players.length; i++) { + sum += this.players[i].fitness; } - //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + this.averageFitness = sum / this.players.length; + } + //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //gets baby from the this.players in this species giveMeBaby(innovationHistory) { @@ -160,35 +160,35 @@ class Species { //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //selects a player based on it fitness selectPlayer() { - var fitnessSum = 0; - for (var i = 0; i < this.players.length; i++) { - fitnessSum += this.players[i].fitness; - } - var rand = random(fitnessSum); - var runningSum = 0; + var fitnessSum = 0; + for (var i = 0; i < this.players.length; i++) { + fitnessSum += this.players[i].fitness; + } + var rand = random(fitnessSum); + var runningSum = 0; - for (var i = 0; i < this.players.length; i++) { - runningSum += this.players[i].fitness; - if (runningSum > rand) { - return this.players[i]; - } + for (var i = 0; i < this.players.length; i++) { + runningSum += this.players[i].fitness; + if (runningSum > rand) { + return this.players[i]; } - //unreachable code to make the parser happy - return this.players[0]; } - //------------------------------------------------------------------------------------------------------------------------------------------ - //kills off bottom half of the species + //unreachable code to make the parser happy + return this.players[0]; + } + //------------------------------------------------------------------------------------------------------------------------------------------ + //kills off bottom half of the species cull() { - if (this.players.length > 2) { - for (var i = this.players.length / 2; i < this.players.length; i++) { - // this.players.remove(i); - this.players.splice(i, 1); - i--; - } + if (this.players.length > 2) { + for (var i = this.players.length / 2; i < this.players.length; i++) { + // this.players.remove(i); + this.players.splice(i, 1); + i--; } } - //------------------------------------------------------------------------------------------------------------------------------------------ - //in order to protect unique this.players, the fitnesses of each player is divided by the number of this.players in the species that that player belongs to + } + //------------------------------------------------------------------------------------------------------------------------------------------ + //in order to protect unique this.players, the fitnesses of each player is divided by the number of this.players in the species that that player belongs to fitnessSharing() { for (var i = 0; i < this.players.length; i++) { this.players[i].fitness /= this.players.length; diff --git a/sketch.js b/sketch.js index ac32214..31f85e4 100644 --- a/sketch.js +++ b/sketch.js @@ -109,13 +109,13 @@ function drawBrain() { //show the brain of whatever genome is currently showing if (runBest) { population.bestPlayer.brain.drawGenome(startX, startY, w, h); } else - if (humanPlaying) { - showBrain = false; - } else if (showBestEachGen) { - genPlayerTemp.brain.drawGenome(startX, startY, w, h); - } else { - population.players[0].brain.drawGenome(startX, startY, w, h); - } + if (humanPlaying) { + showBrain = false; + } else if (showBestEachGen) { + genPlayerTemp.brain.drawGenome(startX, startY, w, h); + } else { + population.players[0].brain.drawGenome(startX, startY, w, h); + } } //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //writes info about the current player @@ -127,20 +127,20 @@ function writeInfo() { text("Score: " + genPlayerTemp.score, 650, 50); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 10) { - // speed -= 10; - // frameRate(speed); - // prvarln(speed); - // } - // break; + // case '+': //speed up frame rate + // speed += 10; + // frameRate(speed); + // prvarln(speed); + // break; + // case '-': //slow down frame rate + // if(speed > 10) { + // speed -= 10; + // frameRate(speed); + // prvarln(speed); + // } + // break; case 'B': //run the best runBest = !runBest; break;