diff --git a/.gitignore b/.gitignore index 315359a..5a28fda 100755 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ build *.jar /library +/gradle \ No newline at end of file diff --git a/build.gradle b/build.gradle index 555921f..307ff20 100755 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id 'java' } -group 'org.perosal' +group 'com.valentinstamate' version '1.0' repositories { @@ -11,13 +11,10 @@ repositories { dependencies { implementation 'org.processing:core:3.3.7' - implementation 'org.apache.httpcomponents:httpclient:4.5' - implementation 'org.jsoup:jsoup:1.13.1' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.1' implementation fileTree("library") - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2' } test { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100755 index be52383..0000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/src/main/java/MainClass.java b/src/main/java/MainClass.java index ff0d66c..ab2b01e 100644 --- a/src/main/java/MainClass.java +++ b/src/main/java/MainClass.java @@ -4,8 +4,8 @@ public class MainClass { public static void main(String... args) { - SecondaryWindow secondaryWindow = new SecondaryWindow(); - PApplet.runSketch(new String[]{""}, secondaryWindow); +// SecondaryWindow secondaryWindow = new SecondaryWindow(); +// PApplet.runSketch(new String[]{""}, secondaryWindow); MainWindow mainWindow = new MainWindow(); PApplet.runSketch(new String[]{""}, mainWindow); diff --git a/src/main/java/board/Board.java b/src/main/java/board/Board.java index 947e952..c0b4b6a 100755 --- a/src/main/java/board/Board.java +++ b/src/main/java/board/Board.java @@ -7,6 +7,7 @@ import util.Config; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class Board { @@ -38,6 +39,9 @@ public void setOnRefreshListener(Observer observer) { void makeSnakeStep() { for (Snake snake : snakeList) { snake.makeStep(); + int[] vision = snake.getVision(); + System.out.println(Arrays.toString(vision)); + } } @@ -65,6 +69,19 @@ void drawSnakes() { } } + public boolean allSnakesFinished() { + int n = snakeList.size(); + + int snakesFinished = 0; + for (Snake snake : snakeList) { + if (snake.isFinished()) { + snakesFinished++; + } + } + + return n == snakesFinished; + } + void drawBoard() { for (int i = 0; i < Config.BOARD_ROWS; i++) { for (int j = 0; j < Config.BOARD_COLUMNS; j++) { diff --git a/src/main/java/board/snake/Snake.java b/src/main/java/board/snake/Snake.java index 28735e0..e5dfbe8 100755 --- a/src/main/java/board/snake/Snake.java +++ b/src/main/java/board/snake/Snake.java @@ -2,6 +2,7 @@ import board.CellType; import board.snake.food.Food; +import controller.controlers.genetic.GeneticAiUtil; import observer.Observer; import observer.OnFinishObserver; import observer.OnFoodEaten; @@ -11,6 +12,7 @@ public class Snake { + /* dir[0] -> i, dir[1] -> j */ private final int[] direction = new int[]{0, 1}; private final int[][] boardMatrix; @@ -155,9 +157,14 @@ private void onSnakeCollide() { for (OnFinishObserver observer : onFinishObservers) { observer.update(snakeData); } + snakeFinished = true; } + public boolean checkFoodCollision(int i, int j) { + return food.getI() == i && food.getJ() == j; + } + /* FOOD LOGIC */ public void repositionFood() { List freeCells = new ArrayList<>(); @@ -178,10 +185,6 @@ public void repositionFood() { food.updateFoodPosition(i, j); } - public boolean checkFoodCollision(int i, int j) { - return food.getI() == i && food.getJ() == j; - } - public void addPoint() { snakeIncrease = true; score+= 5; @@ -230,6 +233,118 @@ public int[] getDirection() { return new int[]{direction[0], direction[1]}; } + /* Gets a 24 double vector */ + public int[] getVision() { + + // degrees are in reverse because the coords are in reverse + int[] head = direction; + int[] west = GeneticAiUtil.reverse(GeneticAiUtil.rotateVectorInt(head[1], head[0], -90)); + int[] south = GeneticAiUtil.reverse(GeneticAiUtil.rotateVectorInt(head[1], head[0], -180)); + int[] east = GeneticAiUtil.reverse(GeneticAiUtil.rotateVectorInt(head[1], head[0], -270)); + + double[] rotationDiag = GeneticAiUtil.reverse(GeneticAiUtil.rotateVector(head[1], head[0], -45)); + + int[] northWest = GeneticAiUtil.crushedDiagonalsToDirection(rotationDiag); + int[] southWest = GeneticAiUtil.reverse(GeneticAiUtil.rotateVectorInt(northWest[1], northWest[0], -90)); + int[] southEast = GeneticAiUtil.reverse(GeneticAiUtil.rotateVectorInt(northWest[1], northWest[0], -180)); + int[] northEast = GeneticAiUtil.reverse(GeneticAiUtil.rotateVectorInt(northWest[1], northWest[0], -270)); + + int i = getHeadI(); + int j = getHeadJ(); + + int[] headData = getDirectionData(i, j, head); + int[] westData = getDirectionData(i, j, west); + int[] southData = getDirectionData(i, j, south); + int[] eastData = getDirectionData(i, j, east); + + int[] northWestData = getDirectionData(i, j, northWest); + int[] southWestData = getDirectionData(i, j, southWest); + int[] southEastData = getDirectionData(i, j, southEast); + int[] northEastData = getDirectionData(i, j, northEast); + + int[] vision = new int[8 * 3]; + + System.arraycopy(headData, 0, vision, 0, 3); + System.arraycopy(northWestData, 0, vision, 3, 3); + System.arraycopy(westData, 0, vision, 6, 3); + System.arraycopy(southWestData, 0, vision, 9, 3); + System.arraycopy(southData, 0, vision, 12, 3); + System.arraycopy(southEastData, 0, vision, 15, 3); + System.arraycopy(eastData, 0, vision, 18, 3); + System.arraycopy(northEastData, 0, vision, 21, 3); + + return vision; + } + + public double[] getNormalizedVision() { + return normalizeDistances(getVision()); + } + + private int[] getDirectionData(int i, int j, int[] direction) { + int rows = boardMatrix.length; + int cols = boardMatrix[0].length; + + boolean foodFound = false; + boolean tailFound = false; + + int foodDistance = 0; + int tailDistance = 0; + int wallDistance = 0; + + for (; i < rows && i >= 0 && j < cols && j >= 0; + i += direction[0], j += direction[1]) { + + if (!foodFound) { + foodDistance++; + } + + wallDistance++; + + if (!tailFound) { + tailDistance++; + } + + if (checkFoodCollision(i, j)) { + foodFound = true; + } + + if (!tailFound && checkTailCollision(i + direction[0], j + direction[1])) { + tailFound = true; + } + + } + + int maxDistance = Math.max(rows, cols); + + if (!foodFound) { + foodDistance = maxDistance; + } + + if (!tailFound) { + tailDistance = maxDistance; + } + + if (tailFound) { + wallDistance = maxDistance; + } + + return new int[]{foodDistance, tailDistance, wallDistance}; + } + + private double[] normalizeDistances(int[] distances) { + int n = distances.length; + + double[] normalizedDistance = new double[n]; + + double max = Math.max(boardMatrix.length, boardMatrix[0].length); + + for (int i = 0; i < n; i++) { + normalizedDistance[i] = 1.0 * distances[i] / max; + } + + return normalizedDistance; + } + /* CHANGING DIRECTION */ public void moveUp() { if (direction[0] == 1 || !canChangeDirection) { diff --git a/src/main/java/controller/SnakeController.java b/src/main/java/controller/SnakeController.java index 17878dc..95c0e80 100755 --- a/src/main/java/controller/SnakeController.java +++ b/src/main/java/controller/SnakeController.java @@ -13,7 +13,7 @@ public abstract class SnakeController { protected final List snakeList; protected final PApplet pApplet; - SnakeController(PApplet pApplet) { + public SnakeController(PApplet pApplet) { this.pApplet = pApplet; this.snakeList = new ArrayList<>(); this.board = new Board(pApplet, snakeList); diff --git a/src/main/java/controller/HamiltonController.java b/src/main/java/controller/controlers/HamiltonController.java similarity index 99% rename from src/main/java/controller/HamiltonController.java rename to src/main/java/controller/controlers/HamiltonController.java index 0acfdc8..3d81f58 100755 --- a/src/main/java/controller/HamiltonController.java +++ b/src/main/java/controller/controlers/HamiltonController.java @@ -1,6 +1,7 @@ -package controller; +package controller.controlers; import board.snake.Snake; +import controller.SnakeController; import controller.node.Node; import observer.OnUpdateObserver; import processing.core.PApplet; diff --git a/src/main/java/controller/SinglePlayerController.java b/src/main/java/controller/controlers/SinglePlayerController.java similarity index 90% rename from src/main/java/controller/SinglePlayerController.java rename to src/main/java/controller/controlers/SinglePlayerController.java index b13ceac..8f54d7d 100755 --- a/src/main/java/controller/SinglePlayerController.java +++ b/src/main/java/controller/controlers/SinglePlayerController.java @@ -1,6 +1,7 @@ -package controller; +package controller.controlers; import board.snake.Snake; +import controller.SnakeController; import processing.core.PApplet; import processing.event.KeyEvent; diff --git a/src/main/java/controller/TwoPlayersController.java b/src/main/java/controller/controlers/TwoPlayersController.java similarity index 86% rename from src/main/java/controller/TwoPlayersController.java rename to src/main/java/controller/controlers/TwoPlayersController.java index 1928055..c9518a1 100755 --- a/src/main/java/controller/TwoPlayersController.java +++ b/src/main/java/controller/controlers/TwoPlayersController.java @@ -1,10 +1,11 @@ -package controller; +package controller.controlers; import board.snake.Snake; +import controller.SnakeController; import processing.core.PApplet; import processing.event.KeyEvent; -public class TwoPlayersController extends SnakeController{ +public class TwoPlayersController extends SnakeController { private final Snake snakeA; private final Snake snakeB; diff --git a/src/main/java/controller/controlers/genetic/GeneticAiController.java b/src/main/java/controller/controlers/genetic/GeneticAiController.java new file mode 100644 index 0000000..ad9423b --- /dev/null +++ b/src/main/java/controller/controlers/genetic/GeneticAiController.java @@ -0,0 +1,108 @@ +package controller.controlers.genetic; + +import board.snake.Snake; +import controller.SnakeController; +import ga.AbstractGeneticAlgorithm; +import ga.config.GaConfig; +import ga.lambda.BeforeEvaluationEvent; +import ga.member.AbstractMember; +import ga.operators.crossover.AbstractCrossover; +import ga.operators.crossover.OnePointCrossover; +import ga.operators.mutation.AbstractMutation; +import ga.operators.mutation.SimpleMutation; +import ga.operators.selection.AbstractSelection; +import ga.operators.selection.TournamentSelection; +import neural_network.NeuralNetwork; +import processing.core.PApplet; + +import java.util.ArrayList; +import java.util.List; + +public class GeneticAiController extends SnakeController { + + public GeneticAiController(PApplet pApplet) { + super(pApplet); + } + + @Override + public void run() { + + int[] layerSize = new int[]{3, 4, 5, 3}; + int geneLength = SmartSnake.calculateGeneLength(layerSize); + + NeuralNetwork neuralNetwork = new NeuralNetwork(layerSize); + + GaConfig gaConfig = GaConfig.initializeWithParameters( + 100, + 1000, + 1, + geneLength, + 0.0015, + 0.02 + ); + + AbstractMutation abstractMutation = new SimpleMutation(); + AbstractCrossover abstractCrossover = new OnePointCrossover(); + AbstractSelection abstractSelection = new TournamentSelection(); + + AbstractGeneticAlgorithm abstractGeneticAlgorithm = new GeneticAlgorithm( + gaConfig, + abstractMutation, + abstractCrossover, + abstractSelection + ); + + List smartSnakes = new ArrayList<>(); + + BeforeEvaluationEvent beforeEvaluationEvent = (population) -> { + for (AbstractMember abstractMember : population) { + short[] gene = abstractMember.getGeneCopy(); + + Snake snake = new Snake(super.board.getBoardMatrix()); + SmartSnake smartSnake = new SmartSnake(snake, gene, layerSize); + + smartSnakes.add(smartSnake); + + snakeList.clear(); + snakeList.add(smartSnake.getSnake()); + } + + while (!board.allSnakesFinished()) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + for (int i = 0; i < snakeList.size(); i++) { + Snake snake = snakeList.get(i); + AbstractMember abstractMember = population.get(i); + + ((Member) abstractMember).setScore(snake.getScore()); + } + + }; + + new Thread(abstractGeneticAlgorithm::start).start(); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + super.board.start(); + + while (!board.allSnakesFinished()) { + for (SmartSnake smartSnake : smartSnakes) { + Snake snake = smartSnake.getSnake(); + + if (!snake.isFinished()) { + smartSnake.predictNext(); + } + } + } + + } +} diff --git a/src/main/java/controller/controlers/genetic/GeneticAiUtil.java b/src/main/java/controller/controlers/genetic/GeneticAiUtil.java new file mode 100644 index 0000000..c507fa5 --- /dev/null +++ b/src/main/java/controller/controlers/genetic/GeneticAiUtil.java @@ -0,0 +1,118 @@ +package controller.controlers.genetic; + +import java.util.Arrays; + +public class GeneticAiUtil { + + public static double[] brainToVector(double[][][] brain, int[] layerSize) { + int vectorSize = 0; + + for (int i = 0; i < layerSize.length - 1; i++) { + vectorSize += layerSize[i] * layerSize[i + 1]; + } + + double[] vector = new double[vectorSize]; + + int p = 0; + + for (double[][] matrix : brain) { + for (double[] line : matrix) { + for (double value : line) { + vector[p++] = value; + } + } + } + + return vector; + } + + public static double[][][] vectorToBrain(double[] vector, int[] layerSize) { + int layers = layerSize.length; + + double[][][] brain = new double[layers - 1][][]; + + int p = 0; + + for (int l = 0; l < brain.length; l++) { + int n = layerSize[l + 1]; + int m = layerSize[l]; + brain[l] = new double[n][m]; + + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + brain[l][i][j] = vector[p++]; + } + } + } + + return brain; + } + + public static double[] rotateVector(double x, double y, int degree) { + double[] rotatedVector = new double[2]; + + double radians = toRadians(degree); + + rotatedVector[0] = Math.cos(radians) * x - Math.sin(radians) * y; + rotatedVector[1] = Math.sin(radians) * x + Math.cos(radians) * y; + + return rotatedVector; + } + + public static int[] rotateVectorInt(double x, double y, int degree) { + return doubleVectorToInt(rotateVector(x, y, degree)); + } + + /* TODO: move these */ + public static double toRadians(int degrees) { + return 1.0 * degrees * Math.PI / 180.0; + } + + public static int[] doubleVectorToInt(double[] vector) { + int n = vector.length; + + int[] converted = new int[n]; + double roundedConstant = 0.01; + + for (int i = 0; i < n; i++) { + vector[i] += vector[i] < 0 ? -roundedConstant : roundedConstant; + converted[i] = (int) vector[i]; + } + + return converted; + } + + public static int[] reverse(int[] vector) { + int n = vector.length; + + int[] reversed = new int[n]; + + for (int i = n - 1; i >= 0; i--) { + reversed[n - i - 1] = vector[i]; + } + + return reversed; + } + + public static double[] reverse(double[] vector) { + int n = vector.length; + + double[] reversed = new double[n]; + + for (int i = n - 1; i >= 0; i--) { + reversed[n - i - 1] = vector[i]; + } + + return reversed; + } + + public static int[] crushedDiagonalsToDirection(double[] dir) { + int[] newDir = new int[2]; + + newDir[0] = dir[0] < 0 ? -1 : 1; + newDir[1] = dir[1] < 0 ? -1 : 1; + + return newDir; + } + +} diff --git a/src/main/java/controller/controlers/genetic/GeneticAlgorithm.java b/src/main/java/controller/controlers/genetic/GeneticAlgorithm.java new file mode 100644 index 0000000..1f9b884 --- /dev/null +++ b/src/main/java/controller/controlers/genetic/GeneticAlgorithm.java @@ -0,0 +1,26 @@ +package controller.controlers.genetic; + +import ga.AbstractGeneticAlgorithm; +import ga.config.GaConfig; +import ga.member.AbstractMember; +import ga.operators.crossover.AbstractCrossover; +import ga.operators.mutation.AbstractMutation; +import ga.operators.selection.AbstractSelection; + +import java.util.List; + +public class GeneticAlgorithm extends AbstractGeneticAlgorithm { + public GeneticAlgorithm(GaConfig gaConfig, AbstractMutation abstractMutation, AbstractCrossover abstractCrossover, AbstractSelection abstractSelection) { + super(gaConfig, abstractMutation, abstractCrossover, abstractSelection); + } + + @Override + public List generatePopulation() { + return null; + } + + @Override + public List getAbstractMembersFromGene(List list, GaConfig gaConfig, AbstractMutation abstractMutation) { + return null; + } +} diff --git a/src/main/java/controller/controlers/genetic/Member.java b/src/main/java/controller/controlers/genetic/Member.java new file mode 100644 index 0000000..e79342b --- /dev/null +++ b/src/main/java/controller/controlers/genetic/Member.java @@ -0,0 +1,34 @@ +package controller.controlers.genetic; + +import ga.member.AbstractMember; +import java.util.Arrays; + +public class Member extends AbstractMember { + + public Member(int geneLength) { + super(geneLength); + } + + public Member(short[] gene) { + super(gene); + } + + @Override + public void calculateFitness() { + super.fitness = score; + } + + @Override + public void calculateScore() { + + } + + public void setScore(int score) { + super.score = score; + } + + @Override + public AbstractMember getCopy() { + return new Member(Arrays.copyOf(gene, gene.length)); + } +} diff --git a/src/main/java/controller/controlers/genetic/SmartSnake.java b/src/main/java/controller/controlers/genetic/SmartSnake.java new file mode 100644 index 0000000..84af3e4 --- /dev/null +++ b/src/main/java/controller/controlers/genetic/SmartSnake.java @@ -0,0 +1,60 @@ +package controller.controlers.genetic; + +import board.snake.Snake; +import ga.conversion.RangeDoubleToInterval; +import neural_network.NeuralNetwork; + +public class SmartSnake { + private final Snake snake; + + private final NeuralNetwork neuralNetwork; + private final short[] gene; + + /* I know, I know, uppercase */ + private static final double start = -10; + private static final double end = 10; + private static final int precision = 3; + + public SmartSnake(Snake snake, short[] gene, int[] layerSize) { + this.snake = snake; + this.gene = gene; + + double[] weights = RangeDoubleToInterval.toDoubleVector(gene, start, end, precision); + double[][][] brain = GeneticAiUtil.vectorToBrain(weights, layerSize); + + this.neuralNetwork = new NeuralNetwork(brain, layerSize); + } + + public SmartSnake(Snake snake, int[] layerSize) { + this.snake = snake; + this.neuralNetwork = new NeuralNetwork(layerSize); + double[][][] brain = neuralNetwork.getBrainReference(); + + double[] weights = GeneticAiUtil.brainToVector(brain, layerSize); + + this.gene = RangeDoubleToInterval.toBitMapVector(weights, start, end, precision); + } + + public Snake getSnake() { + return snake; + } + + /* 8 directions: for each one sees the distance between the walls, tail and food, in total 24 */ + public void predictNext() { + double[] input; + double[] output; + } + + public static int calculateGeneLength(int[] layerSize) { + int elements = 0; + + for (int i = 0; i < layerSize.length - 1; i++) { + elements += layerSize[i] * layerSize[i + 1]; + } + + int lengthPerElement = RangeDoubleToInterval.calculateBitPointLength(end - start, precision); + + return elements * lengthPerElement; + } + +} diff --git a/src/main/java/util/Config.java b/src/main/java/util/Config.java index 2d3b89b..74019f6 100755 --- a/src/main/java/util/Config.java +++ b/src/main/java/util/Config.java @@ -5,7 +5,7 @@ public abstract class Config { /* CANVAS */ public static final int FRAMERATE = 60; - public static final int REFRESH_RATE = 2; + public static final int REFRESH_RATE = 10; /* BOARD */ public static final int BOARD_WIDTH = 650; diff --git a/src/main/java/util/GameType.java b/src/main/java/util/GameType.java index 144b753..3ef4acb 100755 --- a/src/main/java/util/GameType.java +++ b/src/main/java/util/GameType.java @@ -4,4 +4,5 @@ public class GameType { public static final int SINGLE_PLAYER = 1; public static final int TWO_PLAYERS = 2; public static final int HAMILTON_MODE = 3; + public static final int GENETIC_AI = 4; } diff --git a/src/main/java/window/MainWindow.java b/src/main/java/window/MainWindow.java index 470a4fa..2ec03e7 100755 --- a/src/main/java/window/MainWindow.java +++ b/src/main/java/window/MainWindow.java @@ -1,9 +1,9 @@ package window; -import controller.HamiltonController; -import controller.SinglePlayerController; +import controller.controlers.HamiltonController; +import controller.controlers.SinglePlayerController; import controller.SnakeController; -import controller.TwoPlayersController; +import controller.controlers.TwoPlayersController; import processing.core.PApplet; import util.Config; import util.GameType; @@ -17,7 +17,7 @@ public void settings() { public void setup() { - surface.setLocation(displayWidth / 2, displayHeight / 2 - height / 2); +// surface.setLocation(displayWidth / 2, displayHeight / 2 - height / 2); surface.setTitle("Conquering The Snake"); background(25); diff --git a/src/test/java/Tests.java b/src/test/java/Tests.java old mode 100755 new mode 100644 index 0b46271..6c656f2 --- a/src/test/java/Tests.java +++ b/src/test/java/Tests.java @@ -1,41 +1,84 @@ -import board.snake.SnakeData; -import controller.HamiltonController; +import controller.controlers.genetic.GeneticAiUtil; +import ga.conversion.RangeDoubleToInterval; +import neural_network.math.Matrix; +import neural_network.math.Vector; +import neural_network.weights.WeightsInit; +import neural_network.weights.XavierWeightsInit; import org.junit.jupiter.api.Test; -import request.Backend; -import java.io.IOException; -import java.util.List; +import java.util.Arrays; public class Tests { - @Test - public void test() { - HamiltonController hamiltonController = new HamiltonController(null); - int[] path = hamiltonController.getPath(); + public void brainToVectorTest() { + WeightsInit weightsInit = new XavierWeightsInit(); + + int[] layerDimension = new int[]{4, 6, 4, 2}; + + double[][][] brain = new double[layerDimension.length - 1][][]; - for (int i = 0; i < path.length; i++) { - System.out.printf("%d %d\n", i, path[i]); + for(int i = 0; i < brain.length; ++i) { + int n = layerDimension[i + 1]; + int m = layerDimension[i]; + brain[i] = weightsInit.create(n, m); } + + double[] vector = GeneticAiUtil.brainToVector(brain, layerDimension); + short[] bitmap = RangeDoubleToInterval.toBitMapVector(vector, -10, 10, 3); + double[] reconvertedVector = RangeDoubleToInterval.toDoubleVector(bitmap, -10, 10, 3); + + double[][][] convertedBrain = GeneticAiUtil.vectorToBrain(reconvertedVector, layerDimension); + + System.out.println("Brain\n"); + Matrix.print(brain); + + System.out.printf("Bitmap Length %d\n", bitmap.length); + System.out.println("\nConverted\n"); + + Matrix.print(convertedBrain); } @Test - void getResponse() { - Backend backend = new Backend(); - SnakeData[] snakeDataList = (SnakeData[]) backend.receive(); + public void vectorRotationTest() { + int[] vector = new int[]{0, 1}; - for (SnakeData snakeData : snakeDataList) { - System.out.println(snakeData.score); - } + int[] ve = GeneticAiUtil.rotateVectorInt(vector[0], vector[1], 90); + + System.out.printf("%d %d\n", ve[0], ve[1]); } @Test - void addScore() throws IOException { - SnakeData snakeData = new SnakeData("Snake", 14000, "dsalkj9"); + public void snakeRotation() { + int[] dir = new int[]{0, 1}; // it's reversed + + int[] rotation = GeneticAiUtil.reverse(GeneticAiUtil.rotateVectorInt(dir[1], dir[0], -270)); - Backend backend = new Backend(); - backend.send(snakeData); + System.out.printf("%d %d\n", rotation[0], rotation[1]); } -} + @Test + public void diagonalsTest() { + int[] dir = new int[]{0, 1}; // it's reversed + + double[] rotationDiag = GeneticAiUtil.reverse(GeneticAiUtil.rotateVector(dir[1], dir[0], -45)); + int[] normalized = GeneticAiUtil.crushedDiagonalsToDirection(rotationDiag); + + System.out.printf("%d %d\n", normalized[0], normalized[1]); + + normalized = GeneticAiUtil.reverse(GeneticAiUtil.rotateVectorInt(normalized[1], normalized[0], -180)); + + System.out.printf("%d %d\n", normalized[0], normalized[1]); + } + @Test + public void copyTest() { + int[] v = {1, 6, 3, 4, 5}; + + int[] t = new int[10]; + + System.arraycopy(v, 0, t, 1, v.length); + System.out.println(Arrays.toString(t)); + } + +}