Skip to content

Commit

Permalink
created own neurobot using brain.js
Browse files Browse the repository at this point in the history
modified the rest to work with eneurobots
values now from -1 to 1, no strict decisions
also added the ability to see the distance
  • Loading branch information
exi committed Feb 17, 2011
1 parent 6f0e859 commit c37cff5
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 123 deletions.
131 changes: 131 additions & 0 deletions brain.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
function randinit( range )
{
return (Math.random()*2.0-1.0)*range;
}

function mutate( value, range, rate )
{
var newval;

if( Math.random() <= rate )
{
if( Math.random() <= 0.001 )
{
newval = randinit( range );
}
else
{
newval = value+(Math.random()*2.0-1.0)*rate;
if( newval > range ) newval = range;
if( newval < -range ) newval = -range;
}
}
else
{
newval = value;
}

return newval;
}

function Brain(p_braindepth, p_layersize, p_inputneurons, p_outputneurons) {
this.neurons = new Array();
this.braindepth = p_braindepth;
this.layersize = p_layersize;
this.inputneurons = p_inputneurons;
this.outputneurons = p_outputneurons;

for( var i = 0; i<this.braindepth; i++)
this.neurons.push(new Array(p_layersize));

this.mutateFromParent = function(parent, mutationrate) {
for( var x=0; x<this.neurons.length; x++ ) {
for( var y=0; y<this.neurons[x].length; y++ ) {
this.neurons[x][y] = {};
this.neurons[x][y].inputweights = new Array();
this.neurons[x][y].feedbackweights = new Array();
this.neurons[x][y].activation = 0.0;
this.neurons[x][y].nextact = 0.0;

this.neurons[x][y].bias = mutate( parent.neurons[x][y].bias, 5.0, mutationrate );

if( x != 0 ) {
for( var i=0; i<this.layersize; i++ ) {
this.neurons[x][y].inputweights[i] = mutate( parent.neurons[x][y].inputweights[i], 5.0, mutationrate );
this.neurons[x][y].feedbackweights[i] = mutate( parent.neurons[x][y].feedbackweights[i], 5.0, mutationrate );
}
} else {
for( var i=0; i<32; i++ ) {
this.neurons[x][y].inputweights[i] = mutate( parent.neurons[x][y].inputweights[i], 5.0, mutationrate );
this.neurons[x][y].feedbackweights[i] = 0;
}
}
}
}
};

this.randomInit = function() {
for( var x=0; x<this.neurons.length; x++ ) {
for( var y=0; y<this.neurons[x].length; y++ ) {
this.neurons[x][y] = {};
this.neurons[x][y].inputweights = new Array();
this.neurons[x][y].feedbackweights = new Array();
this.neurons[x][y].activation = 0.0;
this.neurons[x][y].nextact = 0.0;

if( x != 0 ) {
this.neurons[x][y].bias = randinit( 5.0 );
for( var i=0; i<this.layersize; i++ ) {
this.neurons[x][y].inputweights[i] = randinit( 5.0 );
this.neurons[x][y].feedbackweights[i] = randinit( 5.0 );
}
} else {
this.neurons[x][y].bias = randinit( 5.0 );
for( var i=0; i<32; i++ ) {
this.neurons[x][y].inputweights[i] = randinit( 5.0 );
this.neurons[x][y].feedbackweights[i] = 0;
}
}
}
}
}

this.step = function(input) {
for( y=0; y<this.layersize; y++ ) {
this.neurons[0][y].nextact = this.neurons[0][y].bias;
for( i=0; i<input.length; i++ )
this.neurons[0][y].nextact += input[i] * this.neurons[0][y].inputweights[i];
}

for( x=1; x<this.braindepth; x++ ) {
for( y=0; y<this.layersize; y++ ) {
this.neurons[x][y].nextact = this.neurons[x][y].bias;
for( i=0; i<this.layersize; i++ ) {
this.neurons[x][y].nextact += this.neurons[x-1][i].activation * this.neurons[x][y].inputweights[i];
this.neurons[x-1][y].nextact += this.neurons[x][i].activation * this.neurons[x][y].feedbackweights[i];
}
}
}

for( x=0; x<this.braindepth; x++ ) {
for( y=0; y<this.layersize; y++ ) {
this.neurons[x][y].activation = this.neurons[x][y].nextact/(1.0+Math.abs(this.neurons[x][y].nextact));
}
}

var output = new Array(this.outputneurons);

for( var i=0; i<this.outputneurons; i++) {
var stepsize = Math.floor(this.layersize/this.outputneurons);
output[i] = 0;
for( var j=i*stepsize; j<stepsize*(i+1); j++) {
output[i] += this.neurons[this.neurons.length-1][j].activation;
}
output[i] /= stepsize;
output[i] = output[i]/(1.0+Math.abs(output[i]));
}

return output;
}

}
136 changes: 21 additions & 115 deletions neurobot.js → eneurobot.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function mutate( value, range, rate )
var braindepth;
var brainsize;

function neurobot( x, y, rot, parent )
function neurobot( x, y, rot, parent)
{
this.alife = true;
this.rot = rot;
Expand Down Expand Up @@ -103,6 +103,8 @@ function neurobot( x, y, rot, parent )
if( this.color.b < 0 ) this.color.b = 0;
}

this.brain = new Brain(this.braindepth, this.brainsize, 32, 2);

this.neurons = new Array();
for( var i=0; i<this.braindepth; i++ )
{
Expand All @@ -111,69 +113,11 @@ function neurobot( x, y, rot, parent )

if( ! parent )
{
for( var x=0; x<this.braindepth; x++ )
{
for( var y=0; y<this.brainsize; y++ )
{
this.neurons[x][y] = {};
this.neurons[x][y].inputweights = new Array();
this.neurons[x][y].feedbackweights = new Array();
this.neurons[x][y].activation = 0.0;
this.neurons[x][y].nextact = 0.0;

if( x != 0 )
{
this.neurons[x][y].bias = randinit( 5.0 );
for( var i=0; i<this.brainsize; i++ )
{
this.neurons[x][y].inputweights[i] = randinit( 5.0 );
this.neurons[x][y].feedbackweights[i] = randinit( 5.0 );
}
}
else
{
this.neurons[x][y].bias = randinit( 5.0 );
for( var i=0; i<32; i++ )
{
this.neurons[x][y].inputweights[i] = randinit( 5.0 );
this.neurons[x][y].feedbackweights[i] = 0;
}
}
}
}
this.brain.randomInit();
}
else
{
for( var x=0; x<this.braindepth; x++ )
{
for( var y=0; y<this.brainsize; y++ )
{
this.neurons[x][y] = {};
this.neurons[x][y].inputweights = new Array();
this.neurons[x][y].feedbackweights = new Array();
this.neurons[x][y].activation = 0.0;
this.neurons[x][y].nextact = 0.0;

this.neurons[x][y].bias = mutate( parent.neurons[x][y].bias, 5.0, this.mutationrate );

if( x != 0 )
{
for( var i=0; i<this.brainsize; i++ )
{
this.neurons[x][y].inputweights[i] = mutate( parent.neurons[x][y].inputweights[i], 5.0, this.mutationrate );
this.neurons[x][y].feedbackweights[i] = mutate( parent.neurons[x][y].feedbackweights[i], 5.0, this.mutationrate );
}
}
else
{
for( var i=0; i<32; i++ )
{
this.neurons[x][y].inputweights[i] = mutate( parent.neurons[x][y].inputweights[i], 5.0, this.mutationrate );
this.neurons[x][y].feedbackweights[i] = 0;
}
}
}
}
this.brain.mutateFromParent(parent.brain);
}

this.step = function()
Expand All @@ -194,6 +138,7 @@ function neurobot( x, y, rot, parent )
dist = f.x*f.x+f.y*f.y;
if( dist > 150.0*150.0 )
continue;
var distq = dist;

for( var i=0; i<16; i++ )
{
Expand All @@ -211,7 +156,7 @@ function neurobot( x, y, rot, parent )
dist = (p.x-food[j].x)*(p.x-food[j].x)+(p.y-food[j].y)*(p.y-food[j].y);

if( dist <= 25.0 )
this.vision[i] = 1.0;
this.vision[i] = 1.0 - distq/(150*150);
}
}

Expand All @@ -229,6 +174,7 @@ function neurobot( x, y, rot, parent )
dist = f.x*f.x+f.y*f.y;
if( dist > 150.0*150.0 )
continue;
var distq = dist;

for( var i=0; i<16; i++ )
{
Expand All @@ -246,55 +192,15 @@ function neurobot( x, y, rot, parent )
dist = (p.x-bots[j].x)*(p.x-bots[j].x)+(p.y-bots[j].y)*(p.y-bots[j].y);

if( dist <= 25.0 )
this.vision[i+16] = 1.0;
}
}

for( y=0; y<this.brainsize; y++ )
{
this.neurons[0][y].nextact = this.neurons[0][y].bias;
for( i=0; i<32; i++ )
this.neurons[0][y].nextact += this.vision[i] * this.neurons[0][y].inputweights[i];
}

for( x=1; x<this.braindepth; x++ )
for( y=0; y<this.brainsize; y++ )
{
this.neurons[x][y].nextact = this.neurons[x][y].bias;
for( i=0; i<this.brainsize; i++ )
{
this.neurons[x][y].nextact += this.neurons[x-1][i].activation * this.neurons[x][y].inputweights[i];
this.neurons[x-1][y].nextact += this.neurons[x][i].activation * this.neurons[x][y].feedbackweights[i];
this.vision[i+16] = 1.0 - distq/(150*150);
}
}

for( x=0; x<this.braindepth; x++ )
for( y=0; y<this.brainsize; y++ )
{
if( this.neurons[x][y].nextact > 0.0 )
this.neurons[x][y].activation = this.neurons[x][y].nextact/(1.0+this.neurons[x][y].nextact);
else
this.neurons[x][y].activation = 0.0;
}
var output = this.brain.step(this.vision);

var speed = 0.0;
var turnspeed = 0.0;
var speed = Math.abs(output[0]);
var turnspeed = output[1];

for( var i=0; i<this.brainsize/2; i++ )
{
speed += this.neurons[this.braindepth-1][i].activation;
}
speed /= this.brainsize/2;

for( var i=this.brainsize/2; i<this.brainsize; i++ )
{
if( i%2 == 0 )
turnspeed += this.neurons[this.braindepth-1][i].activation;
else
turnspeed -= this.neurons[this.braindepth-1][i].activation;
}
turnspeed /= this.brainsize/2;

this.rot += turnspeed/5.0;

if( this.rot >= 2.0*Math.PI )
Expand Down Expand Up @@ -363,7 +269,7 @@ function neurobot( x, y, rot, parent )
lx = Math.cos( dir )*150.0;
ly = Math.sin( dir )*150.0;

ctx.strokeStyle = "rgba( "+(this.vision[i+16]*127+127)+", "+(this.vision[i]*127+127)+", 127, 0.25 )"
ctx.strokeStyle = "rgba( "+Math.round(this.vision[i+16]*127+127)+", "+Math.round(this.vision[i]*127+127)+", 127, 0.25 )"

ctx.beginPath();
ctx.moveTo( 0, 0 );
Expand All @@ -387,27 +293,27 @@ function neurobot( x, y, rot, parent )
{
var data = "BRAINDATA:1/5;\n";

data += this.brainsize.toString(36) + ":" + this.braindepth.toString(36) + ":" + this.generation.toString(36) + ":" + int_pack( this.mutationrate, 1.0 ) + ":";
data += this.brain.layersize.toString(36) + ":" + this.brain.braindepth.toString(36) + ":" + this.generation.toString(36) + ":" + int_pack( this.mutationrate, 1.0 ) + ":";
data += Math.round(this.color.r).toString(16) + "/" + Math.round(this.color.g).toString(16) + "/" + Math.round(this.color.b).toString(16) + ";\n";

for( var x=0; x<this.braindepth; x++ )
for( var x=0; x<this.brain.braindepth; x++ )
{
for( var y=0; y<this.brainsize; y++ )
for( var y=0; y<this.brain.layersize; y++ )
{
data += int_pack( this.neurons[x][y].bias, 5.0 ) + "/";
data += int_pack( this.brain.neurons[x][y].bias, 5.0 ) + "/";
if( x != 0 )
{
for( var i=0; i<this.brainsize; i++ )
for( var i=0; i<this.brain.layersize; i++ )
{
data += int_pack( this.neurons[x][y].inputweights[i], 5.0 ) + "/";
data += int_pack( this.neurons[x][y].feedbackweights[i], 5.0 ) + "/";
data += int_pack( this.brain.neurons[x][y].inputweights[i], 5.0 ) + "/";
data += int_pack( this.brain.neurons[x][y].feedbackweights[i], 5.0 ) + "/";
}
}
else
{
for( var i=0; i<32; i++ )
{
data += int_pack( this.neurons[x][y].inputweights[i], 5.0 ) + "/";
data += int_pack( this.brain.neurons[x][y].inputweights[i], 5.0 ) + "/";
}
}
data += ":";
Expand Down
6 changes: 4 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
<html>
<head>
<title>Neurobots</title>
<script type="text/javascript" src="neurobot.js"></script>
<!-- <script type="text/javascript" src="neurobot.js"></script> -->
<script type="text/javascript" src="brain.js"></script>
<script type="text/javascript" src="eneurobot.js"></script>
<script type="text/javascript" src="plant.js"></script>
<script type="text/javascript" src="stats.js"></script>
<script type="text/javascript" src="input.js"></script>
Expand All @@ -25,7 +27,7 @@ <h1>Neurobots</h1>
<input type="button" value="Stop" id="stopbutton" onclick="stopsim();">
<input type="button" value="Reset" onclick="resetsim();">
<input type="button" value="Reset Camera" onclick="resetcam();">
FPS:</td><td><span id="fpsspan">0</span>
CylesPS:</td><td><span id="fpsspan">0</span>
</p>

<span id="worldopts">
Expand Down
Loading

0 comments on commit c37cff5

Please sign in to comment.