diff --git a/.nb-gradle/profiles/private/aux-config b/.nb-gradle/profiles/private/aux-config
index af2bccb..fd3bee1 100644
--- a/.nb-gradle/profiles/private/aux-config
+++ b/.nb-gradle/profiles/private/aux-config
@@ -8,7 +8,13 @@
-
+
+ file:/home/fazo/Documents/Git/AIrium/core/src/com/mygdx/game/Game.java
+ file:/home/fazo/Documents/Git/AIrium/core/src/logic/neural/Neuron.java
+ file:/home/fazo/Documents/Git/AIrium/core/src/logic/Creature.java
+ file:/home/fazo/Documents/Git/AIrium/core/src/logic/neural/Brain.java
+ file:/home/fazo/Documents/Git/AIrium/core/src/logic/World.java
+
diff --git a/core/src/com/mygdx/game/Game.java b/core/src/com/mygdx/game/Game.java
index 8c9f642..bcfde4b 100644
--- a/core/src/com/mygdx/game/Game.java
+++ b/core/src/com/mygdx/game/Game.java
@@ -4,6 +4,7 @@ import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import logic.Element;
import logic.World;
@@ -13,14 +14,16 @@ public class Game extends ApplicationAdapter {
private static Game game;
ShapeRenderer shaper;
private World world;
- private float cameraSpeed = 5;
+ private float cameraSpeed = 15;
+ private BitmapFont font;
@Override
public void create() {
+
game = this;
- world = new World(1920, 1080);
+ world = new World(2500, 2500);
shaper = new ShapeRenderer();
- //shaper.setAutoShapeType(true);
+ font = new BitmapFont();
}
@Override
@@ -63,6 +66,7 @@ public class Game extends ApplicationAdapter {
}
}
shaper.setColor(0.3f, 0.3f, 0.3f, 1);
+ // draw borders
shaper.rect(0, 0, world.getWidth(), world.getHeight());
shaper.end();
}
diff --git a/core/src/logic/World.java b/core/src/logic/World.java
index 8f02706..363e53e 100644
--- a/core/src/logic/World.java
+++ b/core/src/logic/World.java
@@ -10,7 +10,6 @@ import java.util.ArrayList;
import java.util.Comparator;
import java.util.logging.Level;
import java.util.logging.Logger;
-import logic.neural.Brain;
/**
*
@@ -18,8 +17,8 @@ import logic.neural.Brain;
*/
public class World {
- private int width, height, generation = 0;
- private final int nPlants, creatPerGen;
+ private final int width, height, nPlants, creatPerGen;
+ private int generation = 0;
public ArrayList elements;
public ArrayList creatures;
public ArrayList graveyard;
@@ -66,12 +65,6 @@ public class World {
public int compare(Creature t, Creature t1) {
// put the highest fitness first (sort in reverse)
return (int) (t1.getFitness() - t.getFitness());
- /*if (t.getFitness() < t1.getFitness()) {
- return -1;
- } else if (t.getFitness() > t1.getFitness()) {
- return 1;
- }
- return 0;*/
}
};
if (graveyard.isEmpty() || restart) { // First gen
@@ -80,42 +73,45 @@ public class World {
spawnCreature();
}
} else { // Evolve previous gen
- // Calculate avg fitness
+ graveyard.sort(creatureComp); // sort by fitness
+ // Prepare best agent list
+ int topSize = (int) Math.floor(graveyard.size() * 0.1f);
+ Creature[] top = new Creature[topSize];
+ // Calculate avg fitness and prepare best agent list
float avgFitness = 0;
- for (Creature c : graveyard) {
+ for (int i = 0; i < graveyard.size(); i++) {
+ Creature c = graveyard.get(i);
+ if (i < topSize) {
+ top[i] = graveyard.get(i);
+ Log.log(Log.INFO, "Gen " + generation + " Top " + (i + 1) + ": " + c.getFitness());
+ }
avgFitness += c.getFitness();
}
avgFitness = avgFitness / graveyard.size();
Log.log(Log.INFO, "Gen " + generation + " done. Avg fitness: " + avgFitness);
- // Start evolution
- graveyard.sort(creatureComp);
- for (int i = 0; i < creatPerGen / 2; i++) {
- Creature c = graveyard.get(i);
- c.reset();
- // Mutate
- if (i != 0) {
- try {
- // create a child
- float[][][] mind = c.getBrain().breed(graveyard.get(i - 1).getBrain().getMap());
- // spawn it
- spawnCreature(mind);
- } catch (Exception ex) {
- // Should never happen
- Logger.getLogger(World.class.getName()).log(Level.SEVERE, null, ex);
- }
+ // Generate children
+ for (Creature c : graveyard) {
+ int first = (int) Math.floor(Math.random() * topSize);
+ int sec = first;
+ while (sec == first) {
+ sec = (int) Math.floor(Math.random() * topSize);
}
- // Mutate parent
- c.getBrain().remap(c.getBrain().getMutatedMap(0.1f));
- // Add it back in
- creatures.add(c);
- elements.add(c);
+ float[][][] n = null;
+ try {
+ n = top[first].getBrain().breed(top[sec].getBrain().getMap());
+ } catch (Exception ex) {
+ // Should not happen
+ Logger.getLogger(World.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ Creature ne = spawnCreature(n);
+ //ne.getBrain().mutate(0.1f); // mutate children
}
graveyard.clear();
generation++;
}
}
- private void spawn(boolean isCreature, float[][][] brainMap) {
+ private Element spawn(boolean isCreature, float[][][] brainMap) {
int x, y, r;
boolean overlaps = false;
if (isCreature) {
@@ -141,11 +137,13 @@ public class World {
}
elements.add(c);
creatures.add(c);
+ return c;
} else {
Log.log(Log.DEBUG, "New Veg: " + x + " " + y);
Vegetable v = new Vegetable(x, y);
elements.add(v);
plants.add(v);
+ return v;
}
}
@@ -153,12 +151,12 @@ public class World {
spawn(false, null);
}
- private void spawnCreature() {
- spawn(true, null);
+ private Creature spawnCreature() {
+ return (Creature) spawn(true, null);
}
- private void spawnCreature(float[][][] b) {
- spawn(true, b);
+ private Creature spawnCreature(float[][][] b) {
+ return (Creature) spawn(true, b);
}
public int getWidth() {
diff --git a/core/src/logic/neural/Brain.java b/core/src/logic/neural/Brain.java
index 43e08cc..2add9ad 100644
--- a/core/src/logic/neural/Brain.java
+++ b/core/src/logic/neural/Brain.java
@@ -149,7 +149,7 @@ public class Brain {
/**
* Get a map of this brain's mind.. with a mutation
*
- * @param mutationFactor the highest this number, the bigger the mutation
+ * @param mutationFactor the higher this number, the bigger the mutation
* @return a mutated brain map of this brain's mind
*/
public float[][][] getMutatedMap(float mutationFactor) {
@@ -165,6 +165,21 @@ public class Brain {
return res;
}
+ /**
+ * Apply a mutation to this brain
+ *
+ * @param mutationFactor the higher this number, the bigger the mutation
+ */
+ public void mutate(float mutationFactor) {
+ for (int i = 1; i < neurons.length; i++) // layers (skip input layer)
+ {
+ for (int j = 0; j < neurons[i].length; j++) // neurons per layer
+ {
+ neurons[i][j].setWeights(neurons[i][j].mutate(mutationFactor));
+ }
+ }
+ }
+
public float[][][] breed(float[][][] map) throws Exception {
float[][][] res = new float[neurons.length - 1][][];
if (map.length != neurons.length - 1) {
diff --git a/desktop/src/com/mygdx/game/desktop/DesktopLauncher.java b/desktop/src/com/mygdx/game/desktop/DesktopLauncher.java
index 5a92449..e7de7e6 100644
--- a/desktop/src/com/mygdx/game/desktop/DesktopLauncher.java
+++ b/desktop/src/com/mygdx/game/desktop/DesktopLauncher.java
@@ -5,11 +5,16 @@ import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.mygdx.game.Game;
public class DesktopLauncher {
- public static void main (String[] arg) {
- LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
- config.height = 600;
- config.width = 800;
- config.resizable = false;
- new LwjglApplication(new Game(), config);
- }
+
+ public static void main(String[] arg) {
+ LwjglApplicationConfiguration.disableAudio = true;
+ LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
+ config.height = 600;
+ config.width = 800;
+ config.resizable = false;
+ config.vSyncEnabled = false; // Setting to false disables vertical sync
+ config.foregroundFPS = 60; // Setting to 0 disables foreground fps throttling
+ config.backgroundFPS = 0; // Setting to 0 disables background fps throttling
+ new LwjglApplication(new Game(), config);
+ }
}