i’ll make it easy and place the walls in without it
here sketch without the tables
int s = 20;
int hw;
int Total = 500;
ArrayList<Enemy> population, saved;
ArrayList<Wall> wall = new ArrayList<Wall>();
int gen;
int mgen = 5;
int mmove = 5;
EndArea ea;
int bests[] = new int[5];
int beste[] = new int[5];
Table wallTable,genTable;
TableRow wallRow,genRow;
int map = 0;
int col;
float hisc,higen;
int ro;
void setup(){
size(700,580);
for (int i = 0; i < 5; i++){
bests[i] = 0;
beste[i] = 0;
}
genTable = loadTable("gen.csv");
genRow = genTable.getRow(0);
ro = genRow.getInt(0);
ro += 1;
genRow.setInt(0,ro);
genRow = genTable.addRow();
saveTable(genTable,"gen.csv");
ea = new EndArea(26,25);
loadSnake();
population = new ArrayList<Enemy>();
saved = new ArrayList<Enemy>();
/*wallTable = loadTable("wall.csv");
col = wallTable.getColumnCount();
hw = height/s - 1;
for (int i = 0; i <= col-1; i++){
int tr = map*2;
wallRow = wallTable.getRow(tr);
int xx = wallRow.getInt(i);
wallRow = wallTable.getRow(tr+1);
int yy = wallRow.getInt(i);
wall.add(new Wall(xx,yy));
}*/
for (int i = 0; i < Total; i++){
population.add(new Enemy());
}
for (int i = 0; i < 29; i++){
wall.add(new Wall(i,0));
wall.add(new Wall(i,28));
wall.add(new Wall(0,i));
wall.add(new Wall(28,i));
}
for (int i = 0; i < 23; i++){
wall.add(new Wall(i,4));
wall.add(new Wall(6 + i,8));
wall.add(new Wall(i,12));
wall.add(new Wall(6 + i,16));
wall.add(new Wall(i,20));
wall.add(new Wall(6 + i,24));
}
}
void draw(){
background(0);
fill(255);
textSize(20);
text("Gen: " + gen, 29 * s, 1 * s);
text("HS: " + int(hisc), 29 * s, 2 * s);
text("HG: " + int(higen), 29 * s, 3 * s);
text("Pop: " + population.size(), 29 * s, 4 * s);
if (population.size() == 0){
nextGeneration();
}
for (Enemy e: population){
e.check();
e.look();
e.think();
}
for (int i = population.size()-1; i >= 0; i--){
Enemy e = population.get(i);
if (e.collide == true || e.won == true || e.failed == true){
saved.add(e);
population.remove(i);
}
}
for (Wall w: wall){
w.show();
}
ea.show();
for (Enemy e: population){
e.show();
}
}
here EndArea
class EndArea{
int x,y;
int h = s*3;
int w = s * 2;
EndArea(int x, int y){
this.x = x*s;
this.y = y*s;
}
void show(){
fill(0,255,0);
rect(x,y,w,h);
}
}
here Enemy
class Enemy{
PVector pos;
int r = 12;
float score = 0;
float fitness = 0;
float nx,ny;
boolean collide = false;
boolean won = false;
boolean failed;
int timer = 100;
int nummove = 0;
float sy,cd,sd;
float[] inputs = new float[12];
NeuralNetwork brain;
Enemy(){
pos = new PVector(2 * s, 2 * s);
sy = pos.y;
sd = dist(ea.x,ea.y,pos.x,pos.y);
nx = pos.x;
ny = pos.y;
brain = new NeuralNetwork(12, 94, 4);
}
Enemy(NeuralNetwork b){
pos = new PVector(2 * s, 2 * s);
sy = pos.y;
sd = dist(ea.x,ea.y,pos.x,pos.y);
nx = pos.x;
ny = pos.y;
brain = b.clone();
}
void mutate(){
brain.mutate(0.1);
}
void think(){
inputs[8] = pos.x;
inputs[9] = pos.y;
inputs[10] = ea.x;
inputs[11] = ea.y;
float[] guess = brain.output(inputs);
if (guess[0] > guess[1] && guess[0] > guess[2] && guess[0] > guess[3]){move(0,-1);}
if (guess[1] > guess[0] && guess[1] > guess[2] && guess[1] > guess[3]){move(0,1);}
if (guess[2] > guess[1] && guess[2] > guess[0] && guess[2] > guess[3]){move(-1,0);}
if (guess[3] > guess[0] && guess[3] > guess[2] && guess[3] > guess[0]){move(1,0);}
}
void show(){
if (timer > -1){timer -= 1;}
if (timer <= 0 && won == false){
float d = dist(nx,ny,pos.x,pos.y);
if (d < s){
failed = true;
}
else {
nx = pos.x;
ny = pos.y;
timer = 40;
cd = dist(ea.x,ea.y,pos.x,pos.y);
if (cd < sd){
sd = cd;
score += 1;
}
}
}
if (pos.y > sy + (s*2)){score += 1;}
fill(255,0,0);
stroke(0);
rect(pos.x,pos.y,s,s);
}
void check(){
for (int i = 0; i < wall.size(); i++){
Wall w = wall.get(i);
float d = dist(w.pos.x,w.pos.y,pos.x,pos.y);
if (d < s){
collide = true;
}
}// wall
if (pos.x >= ea.x && pos.x < ea.x + ea.w && pos.y >= ea.y && pos.y < ea.y + ea.h){
won = true;
score = score * 2;
}
}// check
void move(int xspd, int yspd){
if (won == false){
pos.x += xspd;
pos.y += yspd;
}
xspd = 0;
yspd = 0;
}
void look() {
PVector direction;
for (int i = 0; i< 8; i++) {
// player sees in 16 direction, so we have to divide one full rotation (360 degrees) with 16
// so angle between two nearest directions will be 22.5 degree
direction = PVector.fromAngle(i*(TWO_PI/8));
direction.mult(10);
// get the normalized distance to the ball if found in the current direction
// if got no ball in the current direction, mag will be zero
float mag = lookInDirection(direction);
inputs[i] = mag; //feed this to the input
// this is how the visualisation
stroke(255,0,0);
if (mag > 0) {
direction.mult(1/mag);
direction.add(pos);
fill(0);
//text(1/mag, direction.x, direction.y);
stroke(0, 255,0);
}else{
//if no ball in current direction
direction.mult(60);
direction.add(pos);
stroke(255, 0,0);
}
line(pos.x, pos.y, direction.x, direction.y);
}
}
float lookInDirection(PVector direction) {
PVector position = new PVector(pos.x, pos.y);//the position where we are currently looking for the balls
float distance = 0;
//move once in the desired direction before starting
position.add(direction);
distance +=1;
//look in the direction
while (distance< 60) {
for (Wall a: wall) {
if (a.lookForHit(position) ) {
// found ball
return 1/distance;
}
}
//look further in the direction
position.add(direction);
// next distance
distance +=1;
}
return 0;
}
void saveEnemy() {
//save snakes brain
saveTable(brain.NetToTable(), "data/Snake.csv");
}
}
here GA
void nextGeneration(){
getBest();
for (int i = 0; i < Total-5; i++){
population.add(pickOne());
}
for (int i = 0; i < 5; i++){
population.add(new Enemy());
}
population.add(bestOne());
gen++;
if (gen == 100){
exit();
}
}
Enemy bestOne(){
int index = 0;
index = beste[0];
Enemy b = saved.get(index);
Enemy child = new Enemy(b.brain);
return child;
}
Enemy pickOne(){// pick an enemy from the top 5
int index = 0;
float choose = random(4);
choose = round(choose);
index = beste[int(choose)];
Enemy b = saved.get(index);
Enemy child = new Enemy(b.brain);
child.mutate();
return child;
}
Enemy loadSnake() {
Enemy load = new Enemy();
Table t = loadTable("data/Snake.csv");
load.brain.TableToNet(t);
return load;
}
void getBest(){// loop through all the enemies and get the scores
for (int i = 0; i < saved.size(); i++){
Enemy s = saved.get(i);
if (s.score > bests[0]){
bests[4] = bests[3];
bests[3] = bests[2];
bests[2] = bests[1];
bests[1] = bests[0];
bests[0] = int(s.score);
beste[4] = beste[3];
beste[3] = beste[2];
beste[2] = beste[1];
beste[1] = beste[0];
beste[0] = i;
if (s.score > hisc){
hisc = s.score;
higen = gen;
s.saveEnemy();
}
}
else if (s.score > bests[1]){
bests[4] = bests[3];
bests[3] = bests[2];
bests[2] = bests[1];
bests[1] = int(s.score);
beste[4] = beste[3];
beste[3] = beste[2];
beste[2] = beste[1];
beste[1] = i;
}
else if (s.score > bests[2]){
bests[4] = bests[3];
bests[3] = bests[2];
bests[2] = int(s.score);
beste[4] = beste[3];
beste[3] = beste[2];
beste[2] = i;
}
else if (s.score > bests[3]){
bests[4] = bests[3];
bests[3] = int(s.score);
beste[4] = beste[3];
beste[3] = i;
}
else if (s.score > bests[4]){
bests[4] = int(s.score);
beste[4] = i;
}
}
}
here Matrix, i changed it
class Matrix {
//local variables
int rows;
int cols;
float[][] matrix;
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//constructor
Matrix(int r, int c) {
rows = r;
cols = c;
matrix = new float[rows][cols];
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//constructor from 2D array
Matrix(float[][] m) {
matrix = m;
cols = m.length;
rows = m[0].length;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//print matrix
void output() {
for (int i =0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
print(matrix[i][j] + " ");
}
println(" ");
}
println();
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//multiply by scalar
void multiply(float n ) {
for (int i =0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
matrix[i][j] *= n;
}
}
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//return a matrix which is this matrix dot product parameter matrix
Matrix dot(Matrix n) {
Matrix result = new Matrix(rows, n.cols);
if (cols == n.rows) {
//for each spot in the new matrix
for (int i =0; i<rows; i++) {
for (int j = 0; j<n.cols; j++) {
float sum = 0;
for (int k = 0; k<cols; k++) {
sum+= matrix[i][k]*n.matrix[k][j];
}
result.matrix[i][j] = sum;
}
}
}
return result;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//set the matrix to random ints between -1 and 1
void randomize() {
for (int i =0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
matrix[i][j] = random(-1, 1);
}
}
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//add a scalar to the matrix
void Add(float n ) {
for (int i =0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
matrix[i][j] += n;
}
}
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
///return a matrix which is this matrix + parameter matrix
Matrix add(Matrix n ) {
Matrix newMatrix = new Matrix(rows, cols);
if (cols == n.cols && rows == n.rows) {
for (int i =0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
newMatrix.matrix[i][j] = matrix[i][j] + n.matrix[i][j];
}
}
}
return newMatrix;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//return a matrix which is this matrix - parameter matrix
Matrix subtract(Matrix n ) {
Matrix newMatrix = new Matrix(cols, rows);
if (cols == n.cols && rows == n.rows) {
for (int i =0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
newMatrix.matrix[i][j] = matrix[i][j] - n.matrix[i][j];
}
}
}
return newMatrix;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//return a matrix which is this matrix * parameter matrix (element wise multiplication)
Matrix multiply(Matrix n ) {
Matrix newMatrix = new Matrix(rows, cols);
if (cols == n.cols && rows == n.rows) {
for (int i =0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
newMatrix.matrix[i][j] = matrix[i][j] * n.matrix[i][j];
}
}
}
return newMatrix;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//return a matrix which is the transpose of this matrix
Matrix transpose() {
Matrix n = new Matrix(cols, rows);
for (int i =0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
n.matrix[j][i] = matrix[i][j];
}
}
return n;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//Creates a single column array from the parameter array
Matrix singleColumnMatrixFromArray(float[] arr) {
Matrix n = new Matrix(arr.length, 1);
for (int i = 0; i< arr.length; i++) {
n.matrix[i][0] = arr[i];
}
return n;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//sets this matrix from an array
void fromArray(float[] arr) {
for (int i = 0; i< rows; i++) {
for (int j = 0; j< cols; j++) {
matrix[i][j] = arr[j+i*cols];
}
}
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//returns an array which represents this matrix
float[] toArray() {
float[] arr = new float[rows*cols];
for (int i = 0; i< rows; i++) {
for (int j = 0; j< cols; j++) {
arr[j+i*cols] = matrix[i][j];
}
}
return arr;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//for ix1 matrixes adds one to the bottom
Matrix addBias() {
Matrix n = new Matrix(rows+1, 1);
for (int i =0; i<rows; i++) {
n.matrix[i][0] = matrix[i][0];
}
n.matrix[rows][0] = 1;
return n;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//applies the activation function(sigmoid) to each element of the matrix
Matrix activate() {
Matrix n = new Matrix(rows, cols);
for (int i =0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
n.matrix[i][j] = sigmoid(matrix[i][j]);
}
}
return n;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//sigmoid activation function
float sigmoid(float x) {
float y = 1 / (1 + pow((float)Math.E, -x));
return y;
}
//returns the matrix that is the derived sigmoid function of the current matrix
Matrix sigmoidDerived() {
Matrix n = new Matrix(rows, cols);
for (int i =0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
n.matrix[i][j] = (matrix[i][j] * (1- matrix[i][j]));
}
}
return n;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//returns the matrix which is this matrix with the bottom layer removed
Matrix removeBottomLayer() {
Matrix n = new Matrix(rows-1, cols);
for (int i =0; i<n.rows; i++) {
for (int j = 0; j<cols; j++) {
n.matrix[i][j] = matrix[i][j];
}
}
return n;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//Mutation function for genetic algorithm
void mutate(float mutationRate) {
//for each element in the matrix
for (int i =0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
float rand = random(1);
if (rand<mutationRate) {//if chosen to be mutated
matrix[i][j] += randomGaussian()/5;//add a random value to it(can be negative)
//set the boundaries to 1 and -1
if (matrix[i][j]>1) {
matrix[i][j] = 1;
}
if (matrix[i][j] <-1) {
matrix[i][j] = -1;
}
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//returns a matrix which has a random number of values from this matrix and the rest from the parameter matrix
Matrix crossover(Matrix partner) {
Matrix child = new Matrix(rows, cols);
//pick a random point in the matrix
int randC = floor(random(cols));
int randR = floor(random(rows));
for (int i =0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
if ((i< randR)|| (i==randR && j<=randC)) { //if before the random point then copy from this matric
child.matrix[i][j] = matrix[i][j];
} else { //if after the random point then copy from the parameter array
child.matrix[i][j] = partner.matrix[i][j];
}
}
}
return child;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------
//return a copy of this matrix
Matrix clone() {
Matrix clone = new Matrix(rows, cols);
for (int i =0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
clone.matrix[i][j] = matrix[i][j];
}
}
return clone;
}
}
here NN, also been changed
class NeuralNetwork{
int iNodes;
int hNodes;
int oNodes;
Matrix whi,whh,woh;
NeuralNetwork(int inputs, int hiddenNo, int outputNo){
iNodes = inputs;
oNodes = outputNo;
hNodes = hiddenNo;
whi = new Matrix(hNodes, iNodes +1);
whh = new Matrix(hNodes, hNodes +1);
woh = new Matrix(oNodes, hNodes +1);
whi.randomize();
whh.randomize();
woh.randomize();
}
float mut(float val, float rate){
if (random(1) > rate){
return val + randomGaussian() * .1;
} else{
return val;
}
}
NeuralNetwork clone() {
NeuralNetwork clone = new NeuralNetwork(iNodes, hNodes, oNodes);
clone.whi = whi.clone();
clone.whh = whh.clone();
clone.woh = woh.clone();
return clone;
}
void mutate(float mr) {
//mutates each weight matrix
whi.mutate(mr);
whh.mutate(mr);
woh.mutate(mr);
}
float[] output(float[] inputsArr) {
//convert array to matrix
//Note woh has nothing to do with it its just a function in the Matrix class
Matrix inputs = woh.singleColumnMatrixFromArray(inputsArr);
//add bias
Matrix inputsBias = inputs.addBias();
//apply layer one weights to the inputs
Matrix hiddenInputs = whi.dot(inputsBias);
//pass through activation function(sigmoid)
Matrix hiddenOutputs = hiddenInputs.activate();
//add bias
Matrix hiddenOutputsBias = hiddenOutputs.addBias();
//apply layer two weights
Matrix hiddenInputs2 = whh.dot(hiddenOutputsBias);
Matrix hiddenOutputs2 = hiddenInputs2.activate();
Matrix hiddenOutputsBias2 = hiddenOutputs2.addBias();
//apply level three weights
Matrix outputInputs = woh.dot(hiddenOutputsBias2);
//pass through activation function(sigmoid)
Matrix outputs = outputInputs.activate();
//convert to an array and return
return outputs.toArray();
}////////////////////////////////////////////////////////////////////////////
NeuralNetwork crossover(NeuralNetwork partner) {
//creates a new child with layer matrices from both parents
NeuralNetwork child = new NeuralNetwork(iNodes, hNodes, oNodes);
child.whi = whi.crossover(partner.whi);
child.whh = whh.crossover(partner.whh);
child.woh = woh.crossover(partner.woh);
return child;
}
Table NetToTable() {
//create table
Table t = new Table();
//convert the matricies to an array
float[] whiArr = whi.toArray();
float[] whhArr = whh.toArray();
float[] wohArr = woh.toArray();
//set the amount of columns in the table
for (int i = 0; i< max(whiArr.length, whhArr.length, wohArr.length); i++) {
t.addColumn();
}
//set the first row as whi
TableRow tr = t.addRow();
for (int i = 0; i< whiArr.length; i++) {
tr.setFloat(i, whiArr[i]);
}
//set the second row as whh
tr = t.addRow();
for (int i = 0; i< whhArr.length; i++) {
tr.setFloat(i, whhArr[i]);
}
//set the third row as woh
tr = t.addRow();
for (int i = 0; i< wohArr.length; i++) {
tr.setFloat(i, wohArr[i]);
}
//return table
return t;
}
void TableToNet(Table t) {
//create arrays to tempurarily store the data for each matrix
float[] whiArr = new float[whi.rows * whi.cols];
float[] whhArr = new float[whh.rows * whh.cols];
float[] wohArr = new float[woh.rows * woh.cols];
//set the whi array as the first row of the table
TableRow tr = t.getRow(0);
for (int i = 0; i< whiArr.length; i++) {
whiArr[i] = tr.getFloat(i);
}
//set the whh array as the second row of the table
tr = t.getRow(1);
for (int i = 0; i< whhArr.length; i++) {
whhArr[i] = tr.getFloat(i);
}
//set the woh array as the third row of the table
tr = t.getRow(2);
for (int i = 0; i< wohArr.length; i++) {
wohArr[i] = tr.getFloat(i);
}
//convert the arrays to matrices and set them as the layer matrices
whi.fromArray(whiArr);
whh.fromArray(whhArr);
woh.fromArray(wohArr);
}
}
here wall
class Wall{
PVector pos;
Wall(int x, int y){
pos = new PVector(x*s,y*s);
}
void show(){
fill(150,75,0);
stroke(0);
rect(pos.x,pos.y,s,s);
}
boolean lookForHit(PVector loc) {
// circle collision detection
if (dist(pos.x, pos.y, loc.x, loc.y)< 50) {
return true;
}
return false;
}
}
you should be able to run this