1
0
mirror of https://github.com/fazo96/AIrium.git synced 2025-03-29 21:18:39 +01:00

some improvements

This commit is contained in:
Enrico Fasoli 2015-07-01 16:03:12 +02:00
parent 18abf1cfd2
commit d5cff69151
8 changed files with 143 additions and 43 deletions

View File

@ -3,10 +3,6 @@
<!--DO NOT EDIT THIS FILE! - Used by the Gradle plugin of NetBeans.--> <!--DO NOT EDIT THIS FILE! - Used by the Gradle plugin of NetBeans.-->
<auxiliary> <auxiliary>
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/> <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group/>
</open-files>
<editor-bookmarks lastBookmarkId="0" xmlns="http://www.netbeans.org/ns/editor-bookmarks/2"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2"> <open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group> <group>
<file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/neural/NeuralConnection.java</file> <file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/neural/NeuralConnection.java</file>
@ -17,5 +13,9 @@
<file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/World.java</file> <file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/World.java</file>
</group> </group>
</open-files> </open-files>
<editor-bookmarks lastBookmarkId="0" xmlns="http://www.netbeans.org/ns/editor-bookmarks/2"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group/>
</open-files>
</auxiliary> </auxiliary>
</gradle-project-properties> </gradle-project-properties>

View File

@ -32,7 +32,7 @@ public class Game extends ApplicationAdapter {
public void render() { public void render() {
// Input // Input
if(Gdx.input.isKeyJustPressed(Input.Keys.SPACE)){ if(Gdx.input.isKeyJustPressed(Input.Keys.SPACE)){
world.getElements().clear(); world.newGen();
} }
// Update // Update
world.update(); world.update();

View File

@ -25,16 +25,16 @@ public class Creature extends Element {
hp = 100; hp = 100;
speed = 0;//(float) Math.random() * 3; speed = 0;//(float) Math.random() * 3;
rotSpeed = 0;//(float) Math.random() - 0.5f; rotSpeed = 0;//(float) Math.random() - 0.5f;
sightRange = 40; sightRange = 60;
fov = (float) Math.PI / 2; fov = (float) Math.PI / 1.5f;
fitness = 100; fitness = 100;
brain = new Brain(3, 2, 1, 4); brain = new Brain(3, 2, 2, 8);
} }
@Override @Override
public void update() { public void update() {
// apply hunger // apply hunger
hp -= 0.1f; hp -= 0.5f;
if (hp < 0) { if (hp < 0) {
Game.get().getWorld().getGraveyard().add(this); Game.get().getWorld().getGraveyard().add(this);
} }
@ -47,6 +47,12 @@ public class Creature extends Element {
// apply speed // apply speed
float xMul = (float) Math.cos(dir), yMul = (float) Math.sin(dir); float xMul = (float) Math.cos(dir), yMul = (float) Math.sin(dir);
move(xMul * speed, yMul * speed); 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; dir += rotSpeed;
// try eating // try eating
eat(); eat();
@ -81,7 +87,11 @@ public class Creature extends Element {
float[] actions = brain.compute(); float[] actions = brain.compute();
System.out.println("Accel: " + actions[0] + " Rot: " + actions[1]); System.out.println("Accel: " + actions[0] + " Rot: " + actions[1]);
speed = actions[0]*max_speed; speed = actions[0]*max_speed;
rotSpeed = actions[1] - 1f; rotSpeed = actions[1]/10;
}
public void setHp(float hp) {
this.hp = hp;
} }
@Override @Override
@ -92,7 +102,7 @@ public class Creature extends Element {
// Eye // Eye
double relX = Math.cos(dir) * getSize(), relY = Math.sin(dir) * getSize(); double relX = Math.cos(dir) * getSize(), relY = Math.sin(dir) * getSize();
if (sight != null) { if (sight != null) {
float c = sight.getDistance() / sightRange; float c = sight.getDistance() / sightRange*2 + sightRange;
if (sight.getElement() instanceof Creature) { if (sight.getElement() instanceof Creature) {
s.setColor(c, 0, 0, 1); s.setColor(c, 0, 0, 1);
} else if (sight.getElement() instanceof Vegetable) { } else if (sight.getElement() instanceof Vegetable) {
@ -145,7 +155,7 @@ public class Creature extends Element {
for (Element e : Game.get().getWorld().getElements()) { for (Element e : Game.get().getWorld().getElements()) {
if (e instanceof Vegetable && overlaps(e)) { if (e instanceof Vegetable && overlaps(e)) {
e.setSize(e.getSize() - 0.1f); e.setSize(e.getSize() - 0.1f);
hp ++; hp++;
fitness++; fitness++;
if (hp > 100) { if (hp > 100) {
hp = 100; hp = 100;
@ -154,8 +164,16 @@ public class Creature extends Element {
} }
} }
public Brain getBrain() {
return brain;
}
public void setDirection(float dir) { public void setDirection(float dir) {
this.dir = dir; this.dir = dir;
} }
public float getFitness() {
return fitness;
}
} }

View File

@ -6,6 +6,7 @@
package logic; package logic;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.mygdx.game.Game;
/** /**
* *
@ -22,7 +23,9 @@ public class Vegetable extends Element {
@Override @Override
public void update() { public void update() {
if(getSize() < 0){
Game.get().getWorld().getDeadPlants().add(this);
}
} }
@Override @Override

View File

@ -6,6 +6,8 @@
package logic; package logic;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator;
import logic.neural.Brain;
/** /**
* *
@ -13,34 +15,80 @@ import java.util.ArrayList;
*/ */
public class World { public class World {
public static final int creatPerGen = 10;
private int width, height; private int width, height;
public ArrayList<Element> elements; public ArrayList<Element> elements;
public ArrayList<Element> graveyard; public ArrayList<Creature> creatures;
public ArrayList<Creature> graveyard;
public ArrayList<Vegetable> plants;
public ArrayList<Vegetable> deadPlants;
public World(int width, int height) { public World(int width, int height) {
this.width = width; this.width = width;
this.height = height; this.height = height;
elements = new ArrayList(); elements = new ArrayList();
creatures = new ArrayList();
plants = new ArrayList();
deadPlants = new ArrayList();
graveyard = new ArrayList(); graveyard = new ArrayList();
newGen();
} }
public void update() { 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); elements.removeAll(graveyard);
graveyard.clear(); elements.removeAll(deadPlants);
for(Element e: elements) e.update(); 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<Creature>() {
@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; int x, y, r;
boolean overlaps = false; boolean overlaps = false;
if (isCreature) { if (isCreature) {
@ -60,19 +108,27 @@ public class World {
} while (overlaps); } while (overlaps);
if (isCreature) { if (isCreature) {
System.out.println("New Creat: " + x + " " + y); 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 { } else {
System.out.println("New Veg: " + x + " " + y); 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() { private void spawnVegetable() {
spawn(false); spawn(false, null);
} }
private void spawnCreature() { private void spawnCreature() {
spawn(true); spawn(true, null);
}
private void spawnCreature(Brain b) {
spawn(true, b);
} }
public int getWidth() { public int getWidth() {
@ -87,8 +143,12 @@ public class World {
return elements; return elements;
} }
public ArrayList<Element> getGraveyard() { public ArrayList<Creature> getGraveyard() {
return graveyard; return graveyard;
} }
public ArrayList<Vegetable> getDeadPlants() {
return deadPlants;
}
} }

View File

@ -8,33 +8,38 @@ import java.util.ArrayList;
*/ */
public class Brain { public class Brain {
public static final float bias = 0.5f;
private ArrayList<Neuron> inputs, outputs, hidden; private ArrayList<Neuron> inputs, outputs, hidden;
public Brain(int nInputs, int nOutputs, int hiddenLayers, int neuronsPerHiddenLayer) { public Brain(int nInputs, int nOutputs, int hiddenLayers, int neuronsPerHiddenLayer) {
inputs = new ArrayList<Neuron>(nInputs); inputs = new ArrayList<Neuron>(nInputs);
outputs = new ArrayList<Neuron>(nOutputs); outputs = new ArrayList<Neuron>(nOutputs);
hidden = new ArrayList<Neuron>(hiddenLayers * neuronsPerHiddenLayer); hidden = new ArrayList<Neuron>(hiddenLayers * neuronsPerHiddenLayer);
populate(nInputs, nOutputs, hiddenLayers, neuronsPerHiddenLayer);
}
private void populate(int nInputs, int nOutputs, int hiddenLayers, int neuronsPerHiddenLayer) {
// Create input neurons // Create input neurons
for (int i = 0; i < nInputs; i++) { for (int i = 0; i < nInputs; i++) {
inputs.add(new Neuron(0)); inputs.add(new Neuron(0,bias));
} }
// popiulate hidden layers // popiulate hidden layers
for (int i = 0; i < hiddenLayers; i++) { for (int i = 0; i < hiddenLayers; i++) {
for (int j = 0; j < neuronsPerHiddenLayer; j++) { for (int j = 0; j < neuronsPerHiddenLayer; j++) {
// create neuron // create neuron
Neuron n = new Neuron(i + 1); Neuron n = new Neuron(i + 1,bias);
// add connections // add connections
for (Neuron s : inputs) { for (Neuron s : inputs) {
n.getInputs().add(new NeuralConnection(randWeight(), s)); n.getInputs().add(new NeuralConnection(randWeight(), s));
} }
hidden.add(n); 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 // populate output layer
for (int i = 0; i < nOutputs; i++) { for (int i = 0; i < nOutputs; i++) {
// add neuron // add neuron
Neuron n = new Neuron(hiddenLayers + 1); Neuron n = new Neuron(hiddenLayers + 1,bias);
int conn = 0; int conn = 0;
for (Neuron s : hidden) { for (Neuron s : hidden) {
// add connections where applicable // add connections where applicable
@ -43,13 +48,13 @@ public class Brain {
n.getInputs().add(new NeuralConnection(randWeight(), s)); 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); outputs.add(n);
} }
} }
private float randWeight(){ private float randWeight() {
return (float) Math.random()*2-1f; return (float) Math.random()*5 - 2.5f;
} }
public void input(float[] values) { public void input(float[] values) {
@ -63,7 +68,7 @@ public class Brain {
n.clearCachedValue(); n.clearCachedValue();
} }
float[] res = new float[outputs.size()]; float[] res = new float[outputs.size()];
for (int i=0;i<outputs.size();i++) { for (int i = 0; i < outputs.size(); i++) {
Neuron n = outputs.get(i); Neuron n = outputs.get(i);
n.clearCachedValue(); n.clearCachedValue();
res[i] = n.compute(); res[i] = n.compute();
@ -71,4 +76,8 @@ public class Brain {
return res; return res;
} }
public void mutate(float mutationFactor) {
for(Neuron n : hidden) n.mutate(mutationFactor);
}
} }

View File

@ -19,6 +19,7 @@ public class NeuralConnection {
public NeuralConnection(float weight, Neuron source) { public NeuralConnection(float weight, Neuron source) {
this.source = source; this.source = source;
this.weight = weight;
} }
public float compute() { public float compute() {
@ -30,6 +31,11 @@ public class NeuralConnection {
return cachedValue = source.compute() * getWeight(); return cachedValue = source.compute() * getWeight();
} }
public void mutate(float mutationFactor) {
float mutation = (float) (Math.random() * mutationFactor - mutationFactor/2);
weight += mutation;
}
public void clearCachedValue() { public void clearCachedValue() {
cachedValueValid = false; cachedValueValid = false;
} }

View File

@ -20,7 +20,7 @@ public class Neuron {
private float cachedValue; private float cachedValue;
private boolean cachedValueValid = false; private boolean cachedValueValid = false;
public Neuron(int layer) { public Neuron(int layer, float bias) {
this.layer = layer; this.layer = layer;
inputs = new ArrayList<NeuralConnection>(); inputs = new ArrayList<NeuralConnection>();
} }
@ -44,6 +44,10 @@ public class Neuron {
return cachedValue; return cachedValue;
} }
public void mutate(float mutationFactor){
for(NeuralConnection n : inputs) n.mutate(mutationFactor);
}
public void setOutput(float output) { public void setOutput(float output) {
isInputNeuron = true; isInputNeuron = true;
this.output = output; this.output = output;