mirror of
https://github.com/fazo96/AIrium.git
synced 2025-03-29 21:18:39 +01:00
some improvements
This commit is contained in:
parent
18abf1cfd2
commit
d5cff69151
@ -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>
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user