to change from 16 to 8 i wold just change the 2 16s in look right?
Yep, change that two 16s
Is there a way to use the look function but make the line point frontwards instead at an angle, I guess frontwards is relative to the game lol, but when I look at the lines in my game all are hitting walls. I was wanting one to point the way the enemy should go. You can see my course in the picture I posted yesterday.
it would be easier if i could run your codes. are you using processing ide? or something else? i have the latest version of processing, and i still cannot run your codes
Processing 3.5.3. Are you sure you just can’t run it because you dont got the table? or did you comment that out?
lemme check the csv file
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
im stuck at those static methods you have written before in matrix class. and got some other errors due to that in nn too. now i can run the codes you just posted with some other csvs commented out
add this import java.io.File; to top it might be needed
Did you get it to work?
i found some problems.
in wall class, you cannot use circle collision detection. you have to use collision detection for rectangle since it is a block
boolean lookForHit(PVector loc) {
// circle collision detection
//if (dist(pos.x, pos.y, loc.x, loc.y)< 50) {
//rectangle collision detection
if(loc.x > pos.x && loc.x < pos.x + s && loc.y > pos.y && loc.y < pos.y + s){
return true;
}
return false;
}
like youve been using in check() function
if (pos.x >= ea.x && pos.x < ea.x + ea.w && pos.y >= ea.y && pos.y < ea.y + ea.h){
then the problem with normalization
inputs[8] = pos.x;
inputs[9] = pos.y;
inputs[10] = ea.x;
inputs[11] = ea.y;
dont forget to normalize the value first when it comes to be fired through the NN
inputs[10] = ea.x;
inputs[11] = ea.y;
just input the distance to the endarea. its better than its position.
and for this
inputs[8] = pos.x;
inputs[9] = pos.y;
you can just ignore its current position, since the player got enough information.
btw, the program will run smoothier if there are no strokes to be dislpayed. stroke() function is bad in performance
you can just increase how many directions the player sees, otherwise, you can manipulate the starting angle while scanning its environment
in the look() function, you can change the high of accuracy it get while scanning by decrease the direction magnitude direction.mult(10);
just change it to like direction.mult(5);
so make the dist input 8? and fix the wall anything else?
1/dist();
anyway
little hack,
distance calculation between two point with dist()
function is bad too. you can replace it with this
float dx = pos.x - target.x;
float dy = pos.y - target.y;
float d = sqrt(sq(dx) + sq(dy)); //simple euclidean distance formula
it do the same, but faster
Nice, cool. Do I normalize it the same way?
right
//ignore this. just make sure the character more than 20