diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..0cbf9cd
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index ae3c172..0000000
--- a/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/bin/
diff --git a/TheGame/.project b/.project
similarity index 92%
rename from TheGame/.project
rename to .project
index fb4cb30..c68be4e 100644
--- a/TheGame/.project
+++ b/.project
@@ -1,6 +1,6 @@
- frogger
+ Full Algorithm
diff --git a/TheGame/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
old mode 100644
new mode 100755
similarity index 100%
rename from TheGame/.settings/org.eclipse.jdt.core.prefs
rename to .settings/org.eclipse.jdt.core.prefs
diff --git a/TheGame/src/Game.java b/TheGame/src/Game.java
deleted file mode 100644
index 72beb2c..0000000
--- a/TheGame/src/Game.java
+++ /dev/null
@@ -1,105 +0,0 @@
-import java.awt.Dimension;
-import java.awt.Graphics;
-import java.awt.Image;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.File;
-import java.io.IOException;
-
-import javax.imageio.ImageIO;
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-import javax.swing.Timer;
-
-public class Game {
- private JFrame frame = new JFrame("Ultra Mario Bros!");
- private JPanel panel;
- private Mario m = new Mario(0, 624);
- private Keyboard keys = new Keyboard(m);
- private int[][] tilelayout = new int[13][13];
- private String[] tileID = {"AIR", "ground", "block"};
- private int offset = 0;
-// private int[] tileData = {1, 2};
- private Timer repaint = new Timer(1, new ActionListener(){
- public void actionPerformed(ActionEvent e) {
- frame.repaint();
-// frame.dispose();
-// JOptionPane.showMessageDialog(null, "You died!\nPoints: " + ((Integer) movey).toString(), "You lost!", JOptionPane.WARNINGMESSAGE);
-// repaint.stop();
-// }
- }
- });
-
- public static void main(String[] args) {
- new Game().start();
- }
-
- private void start() {
- makeFrame();
- repaint.start();
- }
-
- @SuppressWarnings("serial")
- private void makeFrame() {
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- panel = new JPanel() {
- public void paintComponent(Graphics g) {
- super.paintComponent(g);
- m.key(keys.r);
- draw(g);
- }
- };
- frame.add(panel);
-
- for (int x = 0; x < tilelayout.length; x++) {
- tilelayout[12][x] = 1;
- }
-
- panel.repaint();
- panel.setPreferredSize(new Dimension(624, 624));
- panel.addKeyListener(keys);
- panel.setFocusable(true);
- panel.setLayout(null);
- frame.pack();
- frame.setVisible(true);
-
- }
- private void loadNext() {
- for (int y = 0; y < tilelayout.length; y++) {
- for (int x = 1; x < tilelayout.length; x++) {
- tilelayout[y][x - 1] = tilelayout[y][x];
- }
- }
- int[] colay = getNewLine();
- for (int y = 0; y < tilelayout.length; y++) {
- tilelayout[y][tilelayout[y].length - 1] = colay[y];
- }
- }
-
- private int[] getNewLine() {
- return new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
- }
-
- private void draw(Graphics g) {
- offset += m.draw(g, tilelayout);
- while (offset >= 48) {
- loadNext();
- offset -= 48;
- }
-
- for (int y = 0; y < tilelayout.length; y++) {
- for (int x = 0; x < tilelayout.length; x++) {
- int tile = tilelayout[y][x];
- if (tile != 0) {
- Image img;
- try {
- img = ImageIO.read(new File(tileID[tile] + ".png"));
- g.drawImage(img, x * 48 - offset, y * 48, null);
- } catch (IOException e) {
- // Auto-generated catch block
- }
- }
- }
- }
- }
-}
diff --git a/TheGame/.classpath b/_classpath.xml
old mode 100644
new mode 100755
similarity index 79%
rename from TheGame/.classpath
rename to _classpath.xml
index f00af9b..d655412
--- a/TheGame/.classpath
+++ b/_classpath.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/_project.xml b/_project.xml
new file mode 100755
index 0000000..eab011b
--- /dev/null
+++ b/_project.xml
@@ -0,0 +1,17 @@
+
+
+ Full algorithm
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/bin/.gitignore b/bin/.gitignore
new file mode 100644
index 0000000..8e762e5
--- /dev/null
+++ b/bin/.gitignore
@@ -0,0 +1,12 @@
+/Activation.class
+/Game$1.class
+/Game$2.class
+/Game.class
+/GeneticAlgorithm.class
+/Individual.class
+/Keyboard.class
+/Mario.class
+/NeuralNetwork.class
+/NeuralNetworkTester.class
+/Neuron.class
+/Trainer.class
diff --git a/bin/Activation.class b/bin/Activation.class
new file mode 100644
index 0000000..be807e6
Binary files /dev/null and b/bin/Activation.class differ
diff --git a/bin/Game$1.class b/bin/Game$1.class
new file mode 100644
index 0000000..c7a7de3
Binary files /dev/null and b/bin/Game$1.class differ
diff --git a/bin/Game$2.class b/bin/Game$2.class
new file mode 100644
index 0000000..68799f5
Binary files /dev/null and b/bin/Game$2.class differ
diff --git a/bin/Game.class b/bin/Game.class
new file mode 100644
index 0000000..34d1182
Binary files /dev/null and b/bin/Game.class differ
diff --git a/bin/GeneticAlgorithm.class b/bin/GeneticAlgorithm.class
new file mode 100644
index 0000000..907920e
Binary files /dev/null and b/bin/GeneticAlgorithm.class differ
diff --git a/bin/Individual.class b/bin/Individual.class
new file mode 100644
index 0000000..9f9f35f
Binary files /dev/null and b/bin/Individual.class differ
diff --git a/bin/Keyboard.class b/bin/Keyboard.class
new file mode 100644
index 0000000..1de52e4
Binary files /dev/null and b/bin/Keyboard.class differ
diff --git a/bin/Mario.class b/bin/Mario.class
new file mode 100644
index 0000000..bc84736
Binary files /dev/null and b/bin/Mario.class differ
diff --git a/bin/NeuralNetwork.class b/bin/NeuralNetwork.class
new file mode 100644
index 0000000..642d6c7
Binary files /dev/null and b/bin/NeuralNetwork.class differ
diff --git a/bin/NeuralNetworkTester.class b/bin/NeuralNetworkTester.class
new file mode 100644
index 0000000..e5f9e0d
Binary files /dev/null and b/bin/NeuralNetworkTester.class differ
diff --git a/bin/Neuron.class b/bin/Neuron.class
new file mode 100644
index 0000000..4c6c8e7
Binary files /dev/null and b/bin/Neuron.class differ
diff --git a/bin/Trainer.class b/bin/Trainer.class
new file mode 100644
index 0000000..1cb61b0
Binary files /dev/null and b/bin/Trainer.class differ
diff --git a/block.png b/block.png
new file mode 100755
index 0000000..93b1848
Binary files /dev/null and b/block.png differ
diff --git a/data b/data
new file mode 100755
index 0000000..a780344
--- /dev/null
+++ b/data
@@ -0,0 +1,40 @@
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1
+0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1
+0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1
+0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1
+0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1
+0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
diff --git a/ground.png b/ground.png
new file mode 100755
index 0000000..dff8613
Binary files /dev/null and b/ground.png differ
diff --git a/mario.png b/mario.png
new file mode 100755
index 0000000..c5c1b81
Binary files /dev/null and b/mario.png differ
diff --git a/src/Activation.java b/src/Activation.java
new file mode 100755
index 0000000..afb6d94
--- /dev/null
+++ b/src/Activation.java
@@ -0,0 +1,4 @@
+
+public enum Activation {
+ Sigmoid, ReLu, Tanh, None
+}
diff --git a/src/Game.java b/src/Game.java
new file mode 100755
index 0000000..1c321a9
--- /dev/null
+++ b/src/Game.java
@@ -0,0 +1,248 @@
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.Timer;
+
+public class Game {
+ private JFrame frame = new JFrame("Super Mario Bros!");
+ private JPanel panel;
+ private Mario m = new Mario(0, 624);
+ private Keyboard keys = new Keyboard(m);
+ private int[][] tilelayout = new int[13][14];
+ private String[] tileID = {"AIR", "ground"};
+ private int offset = 0;
+ private double fitness = 0;
+ boolean isDone = false;
+ private int frames = 0;
+ public Individual indiv;
+ public static int me = 0;
+ public static int maxFrames = 50;
+ public boolean play = false;
+ public BufferedReader in;
+ private Timer repaint = new Timer(0, new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ frame.repaint();
+ frames += 1;
+ if (m.y < 0 || (frames >= maxFrames && !play)) {
+ //System.out.println("done"+GeneticAlgorithm.numDone);
+ if (m.y < 0) {
+ fitness -= 200;
+ }
+
+ Game.me++;
+ fitness += m.x;
+ //System.out.println("ME"+Game.me);
+ if (indiv != null)
+ indiv.setDone(true);
+ isDone = true;
+ frame.dispose();
+ if (isDone) {
+ repaint.stop();
+ try {
+ in.close();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ System.out.println("My fit: " + fitness);
+ }
+ }
+ }
+ });
+
+ public static void main(String[] args) {
+ new Game().start();
+ }
+
+ void start() {
+ //System.out.println("THREAD: "+Thread.currentThread().getId()+ " "+getFitness());
+ makeFrame();
+ repaint.start();
+ }
+
+ public double[][] getState() {
+ double[][] doubles = new double[tilelayout.length][tilelayout[0].length - 1];
+ /*/
+ for (int i = 0; i < tilelayout.length; i++) {
+ for (int j = 0; j < tilelayout.length - 1; j++) {
+ doubles[i][j] = tilelayout[i][j] * 5.0;
+ }
+ }
+ /*/
+ for (int i = m.tiley - 6; i < m.tiley + 6; i++) {
+ if (i < 0) continue;
+ if (i > 12) continue;
+ for (int j = m.tilex - 6; j < m.tilex + 6; j++) {
+ if (j < 0) continue;
+ if (j > 13) continue;
+ doubles[i][j] = tilelayout[i][j] * 5.0;
+ }
+ }
+
+
+ return doubles;
+ }
+
+ public void jump() {
+ m.jump();
+ }
+
+ public void moveRight() {
+ m.moveRight();
+ }
+
+ public void moveLeft() {
+ m.moveLeft();
+ }
+
+ public double getFitness() {
+ return fitness;
+ }
+
+ @SuppressWarnings("serial")
+ private void makeFrame() {
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ panel = new JPanel() {
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ m.key(keys.r);
+ draw(g);
+ }
+ };
+ panel.setBackground(new Color(111,196,249));
+ frame.add(panel);
+
+// for (int x = 0; x < tilelayout[0].length; x++) {
+// tilelayout[tilelayout.length - 1][x] = 1;
+// }
+// tilelayout[tilelayout.length - 2][13] = 1;
+
+ try {
+ in = new BufferedReader(new FileReader("data"));
+ String str;
+ for (int x = 0; x < tilelayout[0].length; x++) {
+ str = in.readLine();
+ process(str, x);
+ }
+ } catch (IOException e) {
+ System.out.println("BRUHHHHH");
+ }
+
+// printArray(tilelayout);
+ panel.repaint();
+ panel.setPreferredSize(new Dimension(624, 624));
+ panel.addKeyListener(keys);
+ panel.setFocusable(true);
+ panel.setLayout(null);
+ frame.pack();
+ frame.setVisible(true);
+
+ }
+
+ private void process(String str, int x) {
+ int[] replace = new int[tilelayout.length];
+ for (int y = 0; y < tilelayout.length; y++) {
+ char s = str.charAt(3 * y);
+ int i = Character.getNumericValue(s);
+ replace[y] = i;
+ }
+ for (int y = 0; y < tilelayout.length; y++) {
+ tilelayout[y][x] = replace[y];
+ }
+ }
+
+ /*/ private void printArray(int[][] t) {
+ for (int [] y : t) {
+ for (int x : y) {
+ System.out.print(x + ", ");
+ }
+ System.out.println();
+ }
+ }
+ /*/
+
+ private void loadNext() {
+ for (int y = 0; y < tilelayout.length; y++) {
+ for (int x = 1; x < tilelayout[0].length; x++) {
+ tilelayout[y][x - 1] = tilelayout[y][x];
+ }
+ }
+ try {
+ String str;
+ str = in.readLine();
+ process(str, tilelayout[0].length - 1);
+
+ } catch (Exception e) {
+// e.printStackTrace();
+ int[] colay = getNewLine();
+ for (int y = 0; y < tilelayout.length; y++) {
+ tilelayout[y][tilelayout[y].length - 1] = colay[y];
+ }
+ }
+ }
+
+ private int[] getNewLine() {
+ int[] ans = new int[14];
+ int[] lastcol = new int[14];
+ int HEIGHT = 1;
+
+ for (int y = 0; y < tilelayout.length; y++) {
+ lastcol[y] = tilelayout[y][tilelayout[y].length - 2];
+ }
+
+ for (int y = 0; y < lastcol.length; y++) {
+ if (lastcol[y] == 1) {
+ try {
+ ans[(int) (Math.random() * (lastcol.length - y + HEIGHT)) + y - HEIGHT] = 1;
+ } catch (IndexOutOfBoundsException e) {
+ //System.out.println("ERRRRRROOOOOOOOOOOAAAAAAAARRRRRR");
+ //System.out.println(y);
+ //System.out.println(HEIGHT);
+ //System.out.println(lastcol.length);
+ }
+ }
+ }
+
+ ans[(int) (Math.random() * (lastcol.length))] = 1;
+ ans[(int) (Math.random() * (lastcol.length))] = 0;
+
+ return ans;
+// return new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+ }
+
+ private void draw(Graphics g) {
+// System.out.println(offset);
+ int moved = m.draw(g, tilelayout, offset);
+ offset += moved;
+ fitness += moved;
+ while (offset >= 48) {
+ loadNext();
+ offset -= 48;
+ }
+
+ for (int y = 0; y < tilelayout.length; y++) {
+ for (int x = 0; x < tilelayout[0].length; x++) {
+ int tile = tilelayout[y][x];
+ if (tile != 0) {
+ Image img;
+ try {
+ img = ImageIO.read(new File(tileID[tile] + ".png"));
+ g.drawImage(img, x * 48 - offset, y * 48, null);
+ } catch (IOException e) {
+ // Auto-generated catch block
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/GeneticAlgorithm.java b/src/GeneticAlgorithm.java
new file mode 100755
index 0000000..1e26f82
--- /dev/null
+++ b/src/GeneticAlgorithm.java
@@ -0,0 +1,147 @@
+import java.util.ArrayList;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+public class GeneticAlgorithm {
+ private ArrayList individuals = new ArrayList ();
+ private double mutationRate;
+ private int popSize;
+ private int numInputs;
+ public static int numDone = 0;
+ public int oldBest = 0;
+
+ /**
+ * @author - Sri Kondapalli
+ * @param mutationRate -
+ * @param popSize
+ * @param numInputs
+ */
+
+ public GeneticAlgorithm(double mutationRate, int popSize, int numInputs) {
+ this.mutationRate = mutationRate;
+ this.popSize = popSize;
+ this.numInputs = numInputs;
+ }
+
+ public void start(int times) throws InterruptedException, ExecutionException {
+ for (int i = 0; i < times; i++) {
+ System.out.println("Starting generation "+(i+1));
+ main();
+ }
+ }
+
+ boolean firstTime = true;
+ /**
+ * @author Sri Kondapalli
+ * places an Individual ind into a sorted ArrayList
+ */
+ private void main() throws InterruptedException, ExecutionException {
+ ExecutorService service = Executors.newFixedThreadPool(popSize);
+ ArrayList> futures = new ArrayList>();
+ if (firstTime) {
+ for(int i = 0; i < popSize; i++) {
+ Individual ind = new Individual(numInputs);
+ futures.add(service.submit(ind));
+ }
+ firstTime = false;
+ }
+ else {
+ for (Individual indi : individuals) {
+ futures.add(service.submit(indi));
+ }
+ }
+ System.out.println("Population size is " + popSize);
+ double mean = 0;
+ double best = 0;
+ while (true) {
+ Thread.sleep(1);
+ //System.out.println("num done: "+numDone);
+ if (GeneticAlgorithm.numDone >= popSize-1) {
+ System.out.println("Saving Results...");
+ individuals = new ArrayList();
+ for (int i = 0; i < futures.size(); i++) {
+ Individual ind = futures.get(i).get();
+ mean += ind.getFitness();
+ if (ind.getFitness()>best)
+ best = ind.getFitness();
+ int x = 0;
+ while (x < individuals.size() && individuals.get(x).getFitness() >= ind.getFitness()) {
+ x++;
+ }
+ individuals.add(x, ind);
+ }
+ break;
+ }
+ }
+ System.out.println("Generation Score: " + (mean / individuals.size()));
+ System.out.println("Best Fitness: "+ (best));
+ Game.maxFrames += 10;//(int) ((best - oldBest) / 200.0) + 1;
+ //mutationRate = mutationRate * (oldBest / best + 0.5);
+// if (mutationRate > 1) {
+// mutationRate = 0.9999;
+// }
+ //mutationRate = 0.99;
+
+ oldBest = (int) best;
+ System.out.println(Game.maxFrames);
+ System.out.println(mutationRate);
+ GeneticAlgorithm.numDone = 0;
+ select();
+ }
+
+
+ private void select() {
+
+ /**
+ * @author Sri Kondapalli
+ *
+ * Adds the best individuals from the individuals arrayList, and reproduces pairs of best 70 individuals
+ * adds 30 new individuals to maintain population size(100).
+ */
+ System.out.println("Selecting...");
+ int initSize = individuals.size();
+ ArrayList theBest = new ArrayList();
+// for(int i = 0; i < individuals.size() * 0.3; i++) {
+// //System.out.println("WAITING HERE12");
+// theBest.add(individuals.get(i));
+//
+// }
+// for(int i = 0; i < individuals.size() * 0.7; i++) {
+// //System.out.println("WAITING HERE1" + " " + i + " " + individuals.size() * 0.69);
+// NeuralNetwork m1 = NeuralNetwork.reproduce(individuals.get((int) (Math.random() * individuals.size() * 0.3)).getNN(), individuals.get(i).getNN(), mutationRate);
+//// NeuralNetwork m2 = NeuralNetwork.reproduce(individuals.get(i).getNN(), individuals.get(i + 1).getNN(), mutationRate);
+//
+// theBest.add(new Individual(m1));
+//// theBest.add(new Individual(m2));
+// }
+ for (int i=0; i<3; i++)
+ theBest.add(individuals.get(i));
+
+ for (int i=0; i<5; i++) {
+ NeuralNetwork m1 = NeuralNetwork.reproduce(individuals.get(i).getNN(), individuals.get(i+1).getNN(), mutationRate);
+ theBest.add(new Individual(m1));
+ }
+
+ while (theBest.size() < initSize) {
+ //System.out.println("WAITING HERE");
+ theBest.add(new Individual(numInputs));
+ }
+
+ mutationRate -= mutationRate*0.06;
+
+ Individual.predictionThreshold += Individual.predictionThreshold*0.03;
+ individuals = theBest;
+ System.out.println("Finished generation starting next one");
+ System.out.println(Individual.jump+", "+Individual.left+", "+Individual.right);
+ System.out.println("*********************************");
+ }
+}
+
+
+
+
+
+
+
diff --git a/src/Individual.java b/src/Individual.java
new file mode 100755
index 0000000..30e4f0a
--- /dev/null
+++ b/src/Individual.java
@@ -0,0 +1,98 @@
+import java.util.ArrayList;
+import java.util.concurrent.Callable;
+
+public class Individual implements Callable {
+ private NeuralNetwork network;
+ private Game game;
+ public Individual(int numInputs) {
+ network = new NeuralNetwork(numInputs);
+// network.addLayer(40, Activation.ReLu);
+ network.addLayer(4, Activation.Sigmoid);
+ }
+
+ /**
+ * @author Sri Kondapalli
+ * @param NeeralNetwork passed in as a requirement for pairs of individuals to reproduce
+ */
+ public Individual(NeuralNetwork n) {
+ network = n;
+ }
+
+ public double getFitness() {
+ return network.getFitness();
+
+ }
+ public static double predictionThreshold = 0.9;
+ public void play() {
+// System.out.println("PLAYING");
+ double[][] state = game.getState();
+ ArrayList newState = new ArrayList();
+
+ for(int r = 0; r < state.length; r++) {
+ for(int c = 0; c < state[r].length; c++) {
+ newState.add(state[r][c]);
+ }
+ }
+
+ ArrayList actions = network.predict(newState, predictionThreshold);
+
+ if (actions.get(0) == -1) {
+ return;
+ }
+
+ if (actions.size() >= 1 && actions.get(0) >= 1) {
+ game.moveRight();
+ right++;
+ }
+ else if(actions.size() >= 2 && actions.get(1) >= 1) {
+ game.moveLeft();
+ left++;
+ }
+ else if(actions.size() >= 3 && actions.get(2) >= 1) {
+ game.jump();
+ jump++;
+ }
+ }
+ public static int right = 0;
+ public static int left = 0;
+ public static int jump = 0;
+
+ public boolean isDone = false;
+ public void setDone(boolean f) {
+ this.isDone = f;
+ //GeneticAlgorithm.numDone++;
+ //network.setFitness(game.getFitness());
+ //System.out.println("INDIVDONE "+GeneticAlgorithm.numDone);
+ }
+
+ public NeuralNetwork getNN() {
+ return network;
+
+ }
+
+ @Override
+ public String toString() {
+ return "Individual";
+ }
+
+ @Override
+ public Individual call() {
+ game = new Game();
+ game.indiv = this;
+ game.start();
+ while (true) {
+ try {
+ Thread.sleep(1);
+ if (game.isDone || isDone)
+ break;
+ else
+ play();
+ }
+
+ catch (Exception e) {}
+ }
+ network.setFitness(game.getFitness());
+ GeneticAlgorithm.numDone++;
+ return this;
+ }
+}
diff --git a/src/Keyboard.java b/src/Keyboard.java
new file mode 100755
index 0000000..f0dc987
--- /dev/null
+++ b/src/Keyboard.java
@@ -0,0 +1,51 @@
+
+
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+
+public class Keyboard implements KeyListener{
+ Mario m = null;
+ int[] r = new int[3];
+
+ public Keyboard(Mario m) {
+ super();
+ this.m = m;
+ }
+
+ @Override
+ public void keyTyped(KeyEvent e) {
+// System.out.println("What");
+// Hello????
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+// System.out.println("keyPressed = " + KeyEvent.getKeyText(e.getKeyCode()));
+ useKeys(e, 1);
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+// System.out.println("keyReleased = " + KeyEvent.getKeyText(e.getKeyCode()));
+ useKeys(e, 0);
+ }
+
+ public void useKeys(KeyEvent e, int yup) {
+ String s = KeyEvent.getKeyText(e.getKeyCode());
+ if ((s.equals("W")) || (s.equals("Up"))) {
+ r[1] = -1 * yup;
+ }
+ if ((s.equals("S")) || (s.equals("Down"))) {
+ r[1] = 1 * yup;
+ }
+ if ((s.equals("D")) || (s.equals("Right"))) {
+ r[0] = 1 * yup;
+ }
+ if ((s.equals("A")) || (s.equals("Left"))) {
+ r[0] = -1 * yup;
+ }
+ if (s.equals("Z")) {
+ r[2] = 1 * yup;
+ }
+ }
+}
diff --git a/src/Mario.java b/src/Mario.java
new file mode 100755
index 0000000..9855fac
--- /dev/null
+++ b/src/Mario.java
@@ -0,0 +1,194 @@
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+public class Mario{
+ int x = 0;
+ int y = 0;
+ int tilex = 0;
+ int tiley = 0;
+ int prev_x = 0;
+ int prev_y = 0;
+ final int MAX_SPEED = 24;
+ double x_vel = 0;
+ double y_vel = 0;
+ boolean inAir = true;
+ boolean moved = false;
+
+ public Mario(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public boolean collided(int x2, int y2) {
+// System.out.println(Math.abs(x - x2));
+// System.out.println(Math.abs((618 - y) - y2));
+ return ((Math.abs(x - x2) < 48) && (Math.abs((618 - y) - y2) < 48));
+ }
+
+ public void jump() {
+ if (inAir == false) {
+ y_vel = 48;
+// System.out.println("y");
+ }
+ }
+
+ public void moveRight() {
+ if (!moved) {
+ x_vel += 1;
+ moved = true;
+ }
+// System.out.println("x+");
+ }
+
+ public void moveLeft() {
+ if (!moved) {
+ x_vel -= 1;
+ moved = true;
+ }
+// System.out.println("x-");
+ }
+
+ public void key(int[] useKeys) {
+// System.out.print(useKeys[0] + " ");
+// System.out.print(useKeys[1] + " ");
+// System.out.println(useKeys[2]);
+ if (useKeys[1] == -1) {
+ jump();
+ }
+ if (useKeys[0] == 1) {
+ moveRight();
+ }
+ if (useKeys[0] == -1) {
+ moveLeft();
+ }
+
+ if ((useKeys[2] == 1) && (useKeys[0] != 0)) {
+ x_vel = x_vel * 1.2;
+ }
+
+ }
+
+ public int draw(Graphics g, int[][] t, int offset) {
+ int answer = 0;
+
+ tilex = (int) Math.ceil(x / 48.0);
+ tiley = (int) Math.ceil((624 - y) / 48.0);
+ g.setColor(Color.RED);
+ g.drawLine((tilex * 48) - offset, (tiley * 48), (tilex * 48) + 48 - offset, (tiley * 48));
+ g.drawLine((tilex * 48) - offset, (tiley * 48), (tilex * 48) - offset, (tiley * 48) + 48);
+ g.drawLine((tilex * 48) - offset, (tiley * 48) + 48, (tilex * 48) + 48 - offset, (tiley * 48) + 48);
+ g.drawLine((tilex * 48) + 48 - offset, (tiley * 48) + 48, (tilex * 48) + 48 - offset, (tiley * 48));
+ if (tiley < 0) {
+ tiley = 0;
+ }
+ if (tiley > 11) {
+ tiley = 11;
+ }
+// System.out.println(tilex);
+// System.out.println(tiley);
+ if (t[tiley][tilex] == 1 && collided(tilex * 48 - offset, tiley * 48)) {
+// System.out.println("SUGONDESE");
+// System.out.println(x);
+// System.out.println(y);
+// System.out.println(prev_x);
+// System.out.println(prev_y);
+// System.out.println("CO");
+ x = prev_x;
+ y = prev_y;
+ }
+
+ boolean ti;
+ if (tiley == 0) {
+ ti = true;
+ }
+ else {
+ ti = t[tiley - 1][tilex] == 1 && collided(tilex * 48 - offset, (tiley - 1) * 48);
+ }
+
+ if (ti && y_vel > 0) {
+ y_vel = 0;
+ y = y / 48 * 48;
+ }
+
+ if (t[tiley + 1][tilex] == 1) {
+ inAir = false;
+ y = y / 48 * 48;
+ if (y_vel < 0) {
+ y_vel = 0;
+ }
+ }
+ else {
+ inAir = true;
+ }
+
+ if (t[tiley][tilex + 1] == 1 && x_vel > 0 && collided((tilex + 1) * 48 - offset, tiley * 48)) {
+ x_vel = 0;
+ x = tilex * 48 - offset;
+ }
+
+ if (tilex == 0) {
+ ti = true;
+ }
+ else {
+ ti = t[tiley][tilex - 1] == 1 && collided((tilex - 1) * 48 - offset, tiley * 48);
+ }
+
+ if (ti && x_vel < 0) {
+ x_vel = 0;
+ x = tilex * 48 - offset;
+ }
+
+ Image img;
+ try {
+ img = ImageIO.read(new File("mario.png"));
+ g.drawImage(img, x, 624 - y, null);
+ } catch (IOException e) {
+ // 1 2 Oatmeal
+ }
+
+ if (x_vel > MAX_SPEED) {
+ x_vel = MAX_SPEED;
+ }
+ if (x_vel < -MAX_SPEED) {
+ x_vel = -MAX_SPEED;
+ }
+ if (y_vel < -MAX_SPEED) {
+ y_vel = -MAX_SPEED;
+ }
+
+
+ prev_x = x;
+ prev_y = y;
+
+ x = (int) Math.round(x + x_vel);
+ y = (int) Math.round(y + y_vel);
+ x_vel = x_vel * 0.9;
+ if (inAir) {
+ y_vel = y_vel - 5;
+ x_vel = x_vel * 0.9;
+ }
+ if (x > 312) {
+ answer = x - 312;
+ x = 312;
+ }
+ if (x < 0) {
+ x = 0;
+ if (x_vel < 0) {
+ x_vel = 0;
+ }
+ }
+
+ if (y > 624) {
+ y = 624;
+ }
+// System.out.println(x_vel);
+// System.out.println(y_vel);
+ moved = false;
+ return answer;
+ }
+}
diff --git a/src/NeuralNetwork.java b/src/NeuralNetwork.java
new file mode 100755
index 0000000..c04b4d1
--- /dev/null
+++ b/src/NeuralNetwork.java
@@ -0,0 +1,156 @@
+import java.util.ArrayList;
+import java.util.Random;
+import java.io.*;
+
+public class NeuralNetwork implements Serializable {
+ private int numInputs = 0;
+ private double fitness = 0;
+ private ArrayList> layers = new ArrayList>();
+
+ /**
+ * Adds a new layer to the network. No need to add the Input Layer
+ *
+ * @author Arjun
+ * @param numNeurons - Number of Neurons
+ * @param activation - can choose between ReLu, Sigmoid, Tanh
+ * @return void
+ */
+ public void addLayer(int numNeurons, Activation activation) {
+ ArrayList newLayer = new ArrayList();
+ for (int i = 0; i < numNeurons; i++) {
+ if (layers.size() == 0)
+ newLayer.add(new Neuron(activation, numInputs));
+ else
+ newLayer.add(new Neuron(activation, layers.get(layers.size() - 1).size()));
+ }
+ layers.add(newLayer);
+ }
+
+ /**
+ * Predicts the result based on current weights and biases. First it takes the input and gives
+ * it to the first layer, the layer then uses it's neurons to create a new list(neurons use the
+ * propagate method). This list is the new input and is passed into the next layer. This process
+ * keeps on happening until the program has reached the last layer, where it then returns the
+ * index of the highest value neuron(a.k.a the prediction).
+ *
+ * @author Arjun
+ * @param input
+ * @return prediction
+ */
+ public ArrayList predict(ArrayList input, double thresh) {
+ ArrayList oldRes = input;
+ ArrayList newRes = new ArrayList();
+
+ for (int r=0; r();
+ }
+ return getMaxIndexs(oldRes, thresh);
+ }
+
+ public ArrayList predict(ArrayList input) {
+ return predict(input, 0.9);
+ }
+
+ /**
+ * Reproduce two Neural Networks. Analogous to recombination in meiosis.
+ * @author Arjun
+ *
+ * @param nn1 - First Neural Network
+ * @param nn2 - Second Neural Network
+ * @param mutationRate - Higher number will result in more mutations, number should be between 0 and 1
+ * @return returns the offspring of the two neural networks passed in
+ */
+ public static NeuralNetwork reproduce(NeuralNetwork nn1, NeuralNetwork nn2, double mutationRate) {
+ NeuralNetwork newNN = new NeuralNetwork(nn1.numInputs);
+
+ if (mutationRate >= 1 || mutationRate < 0)
+ throw new RuntimeException("Mutation Rate given is not between 0 and 1 ");
+
+ ArrayList> newLayers = new ArrayList>();
+ for (int r=0; r());
+ }
+
+ for (int r=0; r getMaxIndexs(ArrayList l, double thresh) {
+ ArrayList maxIndexs = new ArrayList();
+ boolean didFind = false;
+ for (int i=1; i thresh) {
+ maxIndexs.add(i);
+ didFind = true;
+ }
+ else {
+ maxIndexs.add(0);
+ }
+ }
+ if (!didFind) {
+ maxIndexs = new ArrayList();
+ maxIndexs.add(-1);
+ }
+ return maxIndexs;
+ }
+
+ public void save(String path) {
+ try {
+ FileOutputStream f = new FileOutputStream(path);
+ ObjectOutputStream out = new ObjectOutputStream(f);
+ out.writeObject(this);
+ out.close();
+ f.close();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static NeuralNetwork getFromFile(String path) throws EOFException {
+ try {
+ FileInputStream fi = new FileInputStream(path);
+ ObjectInputStream in;
+ in = new ObjectInputStream(fi);
+ NeuralNetwork net = (NeuralNetwork) in.readObject();
+ in.close();
+ fi.close();
+ return net;
+ }
+ catch (Exception e) {
+ }
+ return null;
+ }
+
+
+ public void setFitness(double f) {
+ fitness = f;
+ }
+
+ public double getFitness() {
+ return fitness;
+ }
+
+ public NeuralNetwork(int numInputs) {
+ this.numInputs = numInputs;
+ }
+
+ public ArrayList> getLayers() {
+ return new ArrayList>(layers);
+ }
+
+ public void setLayers(ArrayList> l) {
+ layers = new ArrayList>(l);
+ }
+}
diff --git a/src/NeuralNetworkTester.java b/src/NeuralNetworkTester.java
new file mode 100755
index 0000000..4c35ad8
--- /dev/null
+++ b/src/NeuralNetworkTester.java
@@ -0,0 +1,85 @@
+import java.util.ArrayList;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class NeuralNetworkTester implements Callable> {
+ public static void main(String args[]) throws InterruptedException, ExecutionException {
+ ExecutorService executor = Executors.newFixedThreadPool(10);
+ int times = 0;
+ while (true) {
+ times++;
+ System.out.println(times+" times");
+ Callable> callable = new NeuralNetworkTester();
+ executor.submit(callable).get();
+ executor.submit(callable).get();
+ }
+ }
+
+ @Override
+ public ArrayList call() throws Exception {
+ return testPredict();
+ }
+
+ public ArrayList testPredict() {
+ NeuralNetwork nn = new NeuralNetwork(5);
+ nn.addLayer(4, Activation.ReLu);
+ nn.addLayer(5, Activation.Sigmoid);
+ nn.addLayer(5, Activation.Sigmoid);
+ nn.addLayer(5, Activation.Sigmoid);
+ nn.addLayer(5, Activation.ReLu);
+ nn.addLayer(5, Activation.Sigmoid);
+ nn.addLayer(5, Activation.Tanh);
+ nn.addLayer(5, Activation.Sigmoid);
+ ArrayList in = new ArrayList();
+ in.add(1.0);
+ in.add(2.0);
+ in.add(1.0);
+ in.add(2.0);
+ in.add(5.0);
+ return nn.predict(in);
+ }
+
+ public void testReproduction() {
+ NeuralNetwork nn2 = new NeuralNetwork(5);
+ nn2.addLayer(4, Activation.ReLu);
+ nn2.addLayer(5, Activation.Sigmoid);
+
+ NeuralNetwork nn1 = new NeuralNetwork(5);
+ nn1.addLayer(4, Activation.ReLu);
+ nn1.addLayer(5, Activation.Sigmoid);
+
+ NeuralNetwork nn3 = NeuralNetwork.reproduce(nn1, nn2, 0.1);
+
+ boolean didFail = false;
+ if (nn3.getLayers().size() != nn1.getLayers().size()) {
+ didFail = true;
+ System.out.println("FAIL");
+ }
+
+ for (int r=0; r weights;
+ private double bias;
+ Activation activation;
+
+ public ArrayList getWeights() {
+ return new ArrayList(weights);
+ }
+
+ public void setWeights(ArrayList w) {
+ weights = new ArrayList(w);
+ }
+
+ public double getBias() {
+ return bias;
+ }
+
+ public void setBias(double newB) {
+ bias = newB;
+ }
+
+ public Neuron(Activation activation, int numInputs) {
+ this.activation = activation;
+ this.bias = (Math.random() * 2) - 1;
+ weights = new ArrayList();
+ for (int i = 0; i < numInputs; i++) {
+ weights.add((Math.random() * 2) - 1);
+ }
+ }
+
+ public Neuron() {
+
+ }
+
+ /**
+ * Returns the output of the neuron given the appropriate inputs. First it multiplies each
+ * input to the corresponding weight, then it sums that value and runs it through an activation
+ * function so that the output is low and non-linear.
+ *
+ * @author Arjun
+ * @param inputs is an ArrayList
+ * @return output of the neuron
+ */
+ public double propagate(ArrayList inputs) {
+ if (inputs.size() != weights.size())
+ throw new Error("Input size given is not assigned");
+
+ double sum = 0;
+ for (int i = 0; i < inputs.size(); i++) {
+ sum += inputs.get(i) * weights.get(i);
+ }
+ sum += bias;
+
+ if (activation == Activation.Sigmoid)
+ sum = (1 / (1 + Math.pow(Math.E, (-1 * sum))));
+
+ else if (activation == Activation.ReLu)
+ sum = Math.max(0.01 * sum, sum);
+
+ else if (activation == Activation.Tanh)
+ sum = 2 / (1 + Math.pow(Math.E, (-2 * sum)));
+
+ return sum;
+ }
+
+ public static void print(ArrayList arrayList) {
+ for (Integer a : arrayList) {
+ System.out.print(a.intValue()+", ");
+ }
+ System.out.print("\n");
+ }
+
+
+ /**
+ * Creates offspring of two parent neurons analogous to meiosis. First it selects one of the two
+ * parents randomly. Then it copies a random section of the parent's weights and adds it to the
+ * offspring's weights.
+ *
+ * @author Arjun
+ * @param n1 First Parent Neuron
+ * @param n2 Second Parent Neuron
+ * @return offspring of the two neurons
+ */
+ public static Neuron reproduce(Neuron n1, Neuron n2, double mutationRate) {
+ if (n1.getWeights().size() != n2.getWeights().size())
+ throw new RuntimeException("Neuron input sizes are not same while trying to reproduce");
+ Neuron n = new Neuron();
+ ArrayList newWeights = n1.getWeights();
+ int lastRandom = 0;
+ while (true) {
+ int rand = randomNum(lastRandom, n1.getWeights().size()-1);
+ for (int i = lastRandom; i < rand; i++) {
+ double num = Math.random();
+ if (num < mutationRate) {
+ newWeights.set(i, Math.random());
+ }
+ else if (num < 0.5) {
+ newWeights.set(i, n2.getWeights().get(i)); // need to clone
+ }
+ else {
+ newWeights.set(i, n1.getWeights().get(i));
+ }
+ }
+
+ if (rand >= n1.getWeights().size()-1) {
+ break;
+ }
+ }
+
+ double num = Math.random();
+ if (num < mutationRate)
+ n.setBias(Math.random());
+ else if (num < 0.5)
+ n.setBias(n1.getBias());
+ else
+ n.setBias(n2.getBias());
+
+ n.setWeights(newWeights);
+ return n;
+ }
+
+ private static int randomNum(int min, int max) {
+ Random r = new Random();
+ return r.nextInt((max - min) + 1) + min;
+ }
+
+ @SuppressWarnings("null")
+ public double compareTo(Neuron n) {
+ double sum = 0.0;
+
+ if (n.getWeights().size() != weights.size())
+ return (Double) null;
+
+ for (int i=0; i