diff --git a/.nb-gradle/profiles/private/aux-config b/.nb-gradle/profiles/private/aux-config
index 29b08c7..3e5ac38 100644
--- a/.nb-gradle/profiles/private/aux-config
+++ b/.nb-gradle/profiles/private/aux-config
@@ -3,10 +3,6 @@
-
-
-
-
file:/home/fazo/Documents/Git/AIrium/core/src/logic/neural/NeuralConnection.java
@@ -17,5 +13,9 @@
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 0df57f7..86e95cc 100644
--- a/core/src/com/mygdx/game/Game.java
+++ b/core/src/com/mygdx/game/Game.java
@@ -32,7 +32,7 @@ public class Game extends ApplicationAdapter {
public void render() {
// Input
if(Gdx.input.isKeyJustPressed(Input.Keys.SPACE)){
- world.getElements().clear();
+ world.newGen();
}
// Update
world.update();
diff --git a/core/src/logic/Creature.java b/core/src/logic/Creature.java
index 4e19f8c..c214a62 100644
--- a/core/src/logic/Creature.java
+++ b/core/src/logic/Creature.java
@@ -25,16 +25,16 @@ public class Creature extends Element {
hp = 100;
speed = 0;//(float) Math.random() * 3;
rotSpeed = 0;//(float) Math.random() - 0.5f;
- sightRange = 40;
- fov = (float) Math.PI / 2;
+ sightRange = 60;
+ fov = (float) Math.PI / 1.5f;
fitness = 100;
- brain = new Brain(3, 2, 1, 4);
+ brain = new Brain(3, 2, 2, 8);
}
@Override
public void update() {
// apply hunger
- hp -= 0.1f;
+ hp -= 0.5f;
if (hp < 0) {
Game.get().getWorld().getGraveyard().add(this);
}
@@ -47,6 +47,12 @@ public class Creature extends Element {
// apply speed
float xMul = (float) Math.cos(dir), yMul = (float) Math.sin(dir);
move(xMul * speed, yMul * speed);
+ if(getX() < 0) setX(0);
+ if(getY() < 0) setX(0);
+ if(getX() > Game.get().getWorld().getWidth())
+ setX(Game.get().getWorld().getWidth());
+ if(getY() > Game.get().getWorld().getHeight())
+ setY(Game.get().getWorld().getHeight());
dir += rotSpeed;
// try eating
eat();
@@ -81,7 +87,11 @@ public class Creature extends Element {
float[] actions = brain.compute();
System.out.println("Accel: " + actions[0] + " Rot: " + actions[1]);
speed = actions[0]*max_speed;
- rotSpeed = actions[1] - 1f;
+ rotSpeed = actions[1]/10;
+ }
+
+ public void setHp(float hp) {
+ this.hp = hp;
}
@Override
@@ -92,7 +102,7 @@ public class Creature extends Element {
// Eye
double relX = Math.cos(dir) * getSize(), relY = Math.sin(dir) * getSize();
if (sight != null) {
- float c = sight.getDistance() / sightRange;
+ float c = sight.getDistance() / sightRange*2 + sightRange;
if (sight.getElement() instanceof Creature) {
s.setColor(c, 0, 0, 1);
} else if (sight.getElement() instanceof Vegetable) {
@@ -145,7 +155,7 @@ public class Creature extends Element {
for (Element e : Game.get().getWorld().getElements()) {
if (e instanceof Vegetable && overlaps(e)) {
e.setSize(e.getSize() - 0.1f);
- hp ++;
+ hp++;
fitness++;
if (hp > 100) {
hp = 100;
@@ -154,8 +164,16 @@ public class Creature extends Element {
}
}
+ public Brain getBrain() {
+ return brain;
+ }
+
public void setDirection(float dir) {
this.dir = dir;
}
+ public float getFitness() {
+ return fitness;
+ }
+
}
diff --git a/core/src/logic/Vegetable.java b/core/src/logic/Vegetable.java
index a88cde7..38c3044 100644
--- a/core/src/logic/Vegetable.java
+++ b/core/src/logic/Vegetable.java
@@ -6,6 +6,7 @@
package logic;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+import com.mygdx.game.Game;
/**
*
@@ -22,7 +23,9 @@ public class Vegetable extends Element {
@Override
public void update() {
-
+ if(getSize() < 0){
+ Game.get().getWorld().getDeadPlants().add(this);
+ }
}
@Override
diff --git a/core/src/logic/World.java b/core/src/logic/World.java
index 2adc2bf..da6c0c1 100644
--- a/core/src/logic/World.java
+++ b/core/src/logic/World.java
@@ -6,6 +6,8 @@
package logic;
import java.util.ArrayList;
+import java.util.Comparator;
+import logic.neural.Brain;
/**
*
@@ -13,34 +15,80 @@ import java.util.ArrayList;
*/
public class World {
+ public static final int creatPerGen = 10;
private int width, height;
public ArrayList elements;
- public ArrayList graveyard;
+ public ArrayList creatures;
+ public ArrayList graveyard;
+ public ArrayList plants;
+ public ArrayList deadPlants;
public World(int width, int height) {
this.width = width;
this.height = height;
elements = new ArrayList();
+ creatures = new ArrayList();
+ plants = new ArrayList();
+ deadPlants = new ArrayList();
graveyard = new ArrayList();
+ newGen();
}
public void update() {
- while (elements.size() < 40) {
- if (Math.random() < 0.4) {
- spawnCreature();
- } else {
- spawnVegetable();
- }
- /*Creature c = new Creature(300,400);
- elements.add(c);
- elements.add(new Vegetable(300,450));*/
- }
elements.removeAll(graveyard);
- graveyard.clear();
- for(Element e: elements) e.update();
+ elements.removeAll(deadPlants);
+ plants.removeAll(deadPlants);
+ creatures.removeAll(graveyard);
+ deadPlants.clear();
+ if (creatures.isEmpty()) {
+ // All dead, next gen
+ newGen();
+ }
+ while (plants.size() < 50) {
+ spawnVegetable();
+ }
+ for (Creature e : creatures) {
+ e.update();
+ }
}
- private void spawn(boolean isCreature) {
+ public void newGen() {
+ elements.removeAll(creatures);
+ creatures.clear();
+ Comparator creatureComp = new Comparator() {
+
+ @Override
+ public int compare(Creature t, Creature t1) {
+ if (t.getFitness() < t1.getFitness()) {
+ return -1;
+ } else if (t.getFitness() > t1.getFitness()) {
+ return 1;
+ }
+ return 0;
+ }
+ };
+ if (graveyard.size() == 0) { // First gen
+ for (int i = 0; i < creatPerGen; i++) {
+ spawnCreature();
+ }
+ } else { // Mutate previous gen
+ //graveyard.sort(creatureComp);
+ int x = 0;
+ for (Creature c : graveyard) {
+ c.getBrain().mutate(5f);
+ if (x < creatPerGen) {
+ c.setHp(100);
+ creatures.add(c);
+ elements.add(c);
+ } else {
+ break;
+ }
+ }
+ graveyard.clear();
+ }
+ }
+
+ private void spawn(boolean isCreature, Brain brain) {
int x, y, r;
boolean overlaps = false;
if (isCreature) {
@@ -60,19 +108,27 @@ public class World {
} while (overlaps);
if (isCreature) {
System.out.println("New Creat: " + x + " " + y);
- elements.add(new Creature(x, y));
+ Creature c = new Creature(x, y);
+ elements.add(c);
+ creatures.add(c);
} else {
System.out.println("New Veg: " + x + " " + y);
- elements.add(new Vegetable(x, y));
+ Vegetable v = new Vegetable(x, y);
+ elements.add(v);
+ plants.add(v);
}
}
private void spawnVegetable() {
- spawn(false);
+ spawn(false, null);
}
private void spawnCreature() {
- spawn(true);
+ spawn(true, null);
+ }
+
+ private void spawnCreature(Brain b) {
+ spawn(true, b);
}
public int getWidth() {
@@ -87,8 +143,12 @@ public class World {
return elements;
}
- public ArrayList getGraveyard() {
+ public ArrayList getGraveyard() {
return graveyard;
}
-
+
+ public ArrayList getDeadPlants() {
+ return deadPlants;
+ }
+
}
diff --git a/core/src/logic/neural/Brain.java b/core/src/logic/neural/Brain.java
index 0648aa4..f87ec86 100644
--- a/core/src/logic/neural/Brain.java
+++ b/core/src/logic/neural/Brain.java
@@ -8,33 +8,38 @@ import java.util.ArrayList;
*/
public class Brain {
+ public static final float bias = 0.5f;
private ArrayList inputs, outputs, hidden;
public Brain(int nInputs, int nOutputs, int hiddenLayers, int neuronsPerHiddenLayer) {
inputs = new ArrayList(nInputs);
outputs = new ArrayList(nOutputs);
hidden = new ArrayList(hiddenLayers * neuronsPerHiddenLayer);
+ populate(nInputs, nOutputs, hiddenLayers, neuronsPerHiddenLayer);
+ }
+
+ private void populate(int nInputs, int nOutputs, int hiddenLayers, int neuronsPerHiddenLayer) {
// Create input neurons
for (int i = 0; i < nInputs; i++) {
- inputs.add(new Neuron(0));
+ inputs.add(new Neuron(0,bias));
}
// popiulate hidden layers
for (int i = 0; i < hiddenLayers; i++) {
for (int j = 0; j < neuronsPerHiddenLayer; j++) {
// create neuron
- Neuron n = new Neuron(i + 1);
+ Neuron n = new Neuron(i + 1,bias);
// add connections
for (Neuron s : inputs) {
n.getInputs().add(new NeuralConnection(randWeight(), s));
}
hidden.add(n);
- System.out.println("Adding Hidden Layer "+(i+1)+" Neuron "+j+" with "+inputs.size()+" inputs");
+ System.out.println("Adding Hidden Layer " + (i + 1) + " Neuron " + j + " with " + inputs.size() + " inputs");
}
}
// populate output layer
for (int i = 0; i < nOutputs; i++) {
// add neuron
- Neuron n = new Neuron(hiddenLayers + 1);
+ Neuron n = new Neuron(hiddenLayers + 1,bias);
int conn = 0;
for (Neuron s : hidden) {
// add connections where applicable
@@ -43,13 +48,13 @@ public class Brain {
n.getInputs().add(new NeuralConnection(randWeight(), s));
}
}
- System.out.println("Adding Output Layer Neuron "+i+" with "+conn+" inputs");
+ System.out.println("Adding Output Layer Neuron " + i + " with " + conn + " inputs");
outputs.add(n);
}
}
-
- private float randWeight(){
- return (float) Math.random()*2-1f;
+
+ private float randWeight() {
+ return (float) Math.random()*5 - 2.5f;
}
public void input(float[] values) {
@@ -63,7 +68,7 @@ public class Brain {
n.clearCachedValue();
}
float[] res = new float[outputs.size()];
- for (int i=0;i();
}
@@ -44,6 +44,10 @@ public class Neuron {
return cachedValue;
}
+ public void mutate(float mutationFactor){
+ for(NeuralConnection n : inputs) n.mutate(mutationFactor);
+ }
+
public void setOutput(float output) {
isInputNeuron = true;
this.output = output;