mirror of
https://github.com/fazo96/AIrium.git
synced 2025-04-18 01:18:38 +02:00
implemented brains
This commit is contained in:
parent
7c99c1075e
commit
7203371f2e
.nb-gradle/profiles/private
core/src/logic
@ -8,7 +8,14 @@
|
||||
</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/>
|
||||
<group>
|
||||
<file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/neural/NeuralConnection.java</file>
|
||||
<file>file:/home/fazo/Documents/Git/AIrium/core/src/com/mygdx/game/Game.java</file>
|
||||
<file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/neural/Neuron.java</file>
|
||||
<file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/Creature.java</file>
|
||||
<file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/neural/Brain.java</file>
|
||||
<file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/World.java</file>
|
||||
</group>
|
||||
</open-files>
|
||||
</auxiliary>
|
||||
</gradle-project-properties>
|
||||
|
@ -2,6 +2,7 @@ package logic;
|
||||
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.mygdx.game.Game;
|
||||
import logic.neural.Brain;
|
||||
|
||||
/**
|
||||
* A (hopefully) smart biological creature.
|
||||
@ -11,8 +12,10 @@ import com.mygdx.game.Game;
|
||||
public class Creature extends Element {
|
||||
|
||||
public static final int default_radius = 20;
|
||||
public static final float max_speed = 3;
|
||||
|
||||
private float dir, speed, accel, sightRange, fov, fitness, rotSpeed;
|
||||
private Brain brain;
|
||||
private float dir, speed, sightRange, fov, fitness, rotSpeed;
|
||||
private float hp;
|
||||
private Sight sight;
|
||||
|
||||
@ -20,12 +23,12 @@ public class Creature extends Element {
|
||||
super(x, y, default_radius);
|
||||
dir = (float) (Math.random() * 2 * Math.PI);
|
||||
hp = 100;
|
||||
speed = (float) Math.random() * 3;
|
||||
rotSpeed = (float) Math.random() - 0.5f;
|
||||
accel = 0f;
|
||||
speed = 0;//(float) Math.random() * 3;
|
||||
rotSpeed = 0;//(float) Math.random() - 0.5f;
|
||||
sightRange = 40;
|
||||
fov = (float) Math.PI / 2;
|
||||
fitness = 100;
|
||||
brain = new Brain(3, 2, 1, 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -35,12 +38,11 @@ public class Creature extends Element {
|
||||
if (hp < 0) {
|
||||
Game.get().getWorld().getGraveyard().add(this);
|
||||
}
|
||||
speed += accel; // apply acceleration
|
||||
if (speed > 0) {
|
||||
speed -= 0.001; // attrito
|
||||
if (speed > max_speed) {
|
||||
speed = max_speed;
|
||||
}
|
||||
if (speed < 0) {
|
||||
speed = 0;
|
||||
if (speed < -max_speed) {
|
||||
speed = -max_speed;
|
||||
}
|
||||
// apply speed
|
||||
float xMul = (float) Math.cos(dir), yMul = (float) Math.sin(dir);
|
||||
@ -48,11 +50,38 @@ public class Creature extends Element {
|
||||
dir += rotSpeed;
|
||||
// try eating
|
||||
eat();
|
||||
fitness -= 0.1;
|
||||
//fitness -= 0.1;
|
||||
if (dir > 2 * Math.PI) {
|
||||
dir -= 2 * Math.PI;
|
||||
}
|
||||
sight = look();
|
||||
if (dir < 0) {
|
||||
dir += 2 * Math.PI;
|
||||
}
|
||||
sight = look(); // take a look
|
||||
// feed data to brain
|
||||
float[] values = new float[3];
|
||||
// 0: type of sight
|
||||
// 1: distance
|
||||
// 2: angle
|
||||
if (sight == null) {
|
||||
values[0] = 0;
|
||||
values[1] = 1;
|
||||
values[2] = 0;
|
||||
} else if (sight.getElement() instanceof Creature) {
|
||||
values[0] = 1;
|
||||
values[1] = sight.getDistance() / sightRange;
|
||||
values[2] = sight.getAngle();
|
||||
} else {
|
||||
values[0] = 0.5f;
|
||||
values[1] = sight.getDistance() / sightRange;
|
||||
values[2] = sight.getAngle();
|
||||
}
|
||||
brain.input(values);
|
||||
// compute behavior
|
||||
float[] actions = brain.compute();
|
||||
System.out.println("Accel: " + actions[0] + " Rot: " + actions[1]);
|
||||
speed = actions[0]*max_speed;
|
||||
rotSpeed = actions[1] - 1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -116,7 +145,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 += 0.1f;
|
||||
hp ++;
|
||||
fitness++;
|
||||
if (hp > 100) {
|
||||
hp = 100;
|
||||
|
@ -25,8 +25,8 @@ public class World {
|
||||
}
|
||||
|
||||
public void update() {
|
||||
while (elements.size() < 20) {
|
||||
if (Math.random() < 0.2) {
|
||||
while (elements.size() < 40) {
|
||||
if (Math.random() < 0.4) {
|
||||
spawnCreature();
|
||||
} else {
|
||||
spawnVegetable();
|
||||
|
@ -1,9 +1,74 @@
|
||||
package logic.neural;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fazo
|
||||
*/
|
||||
public class Brain {
|
||||
|
||||
private ArrayList<Neuron> inputs, outputs, hidden;
|
||||
|
||||
public Brain(int nInputs, int nOutputs, int hiddenLayers, int neuronsPerHiddenLayer) {
|
||||
inputs = new ArrayList<Neuron>(nInputs);
|
||||
outputs = new ArrayList<Neuron>(nOutputs);
|
||||
hidden = new ArrayList<Neuron>(hiddenLayers * neuronsPerHiddenLayer);
|
||||
// Create input neurons
|
||||
for (int i = 0; i < nInputs; i++) {
|
||||
inputs.add(new Neuron(0));
|
||||
}
|
||||
// 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);
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
// populate output layer
|
||||
for (int i = 0; i < nOutputs; i++) {
|
||||
// add neuron
|
||||
Neuron n = new Neuron(hiddenLayers + 1);
|
||||
int conn = 0;
|
||||
for (Neuron s : hidden) {
|
||||
// add connections where applicable
|
||||
if (s.getLayer() == hiddenLayers) {
|
||||
conn++;
|
||||
n.getInputs().add(new NeuralConnection(randWeight(), s));
|
||||
}
|
||||
}
|
||||
System.out.println("Adding Output Layer Neuron "+i+" with "+conn+" inputs");
|
||||
outputs.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
private float randWeight(){
|
||||
return (float) Math.random()*2-1f;
|
||||
}
|
||||
|
||||
public void input(float[] values) {
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
inputs.get(i).setOutput(values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public float[] compute() {
|
||||
for (Neuron n : hidden) {
|
||||
n.clearCachedValue();
|
||||
}
|
||||
float[] res = new float[outputs.size()];
|
||||
for (int i=0;i<outputs.size();i++) {
|
||||
Neuron n = outputs.get(i);
|
||||
n.clearCachedValue();
|
||||
res[i] = n.compute();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
package logic.neural;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fazo
|
||||
*/
|
||||
public class Connection {
|
||||
private float weight;
|
||||
|
||||
public Connection(float weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public float getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public void setWeight(float weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
}
|
44
core/src/logic/neural/NeuralConnection.java
Normal file
44
core/src/logic/neural/NeuralConnection.java
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package logic.neural;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fazo
|
||||
*/
|
||||
public class NeuralConnection {
|
||||
|
||||
private float weight = 1;
|
||||
|
||||
private final Neuron source;
|
||||
private float cachedValue;
|
||||
private boolean cachedValueValid = false;
|
||||
|
||||
public NeuralConnection(float weight, Neuron source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public float compute() {
|
||||
if (cachedValueValid) {
|
||||
return cachedValue;
|
||||
}
|
||||
// get value from Neuron
|
||||
cachedValueValid = true;
|
||||
return cachedValue = source.compute() * getWeight();
|
||||
}
|
||||
|
||||
public void clearCachedValue() {
|
||||
cachedValueValid = false;
|
||||
}
|
||||
|
||||
public float getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public void setWeight(float weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
}
|
@ -12,5 +12,70 @@ import java.util.ArrayList;
|
||||
* @author fazo
|
||||
*/
|
||||
public class Neuron {
|
||||
private ArrayList<Connection> inputs, outputs;
|
||||
|
||||
private ArrayList<NeuralConnection> inputs;
|
||||
private float bias, output;
|
||||
private boolean isInputNeuron;
|
||||
private int layer;
|
||||
private float cachedValue;
|
||||
private boolean cachedValueValid = false;
|
||||
|
||||
public Neuron(int layer) {
|
||||
this.layer = layer;
|
||||
inputs = new ArrayList<NeuralConnection>();
|
||||
}
|
||||
|
||||
public float compute() {
|
||||
if (isInputNeuron) {
|
||||
return output;
|
||||
}
|
||||
if (cachedValueValid) {
|
||||
return cachedValue;
|
||||
}
|
||||
float a = bias * -1; // activation
|
||||
for (NeuralConnection i : inputs) {
|
||||
a += i.compute();
|
||||
}
|
||||
System.out.println("Computed Value "+a+" for neuron");
|
||||
cachedValueValid = true;
|
||||
// sigmoid function
|
||||
cachedValue = (float) (1 / (1 + Math.pow(Math.E, a * -1)));
|
||||
System.out.println("Computed Value "+cachedValue+" for neuron");
|
||||
return cachedValue;
|
||||
}
|
||||
|
||||
public void setOutput(float output) {
|
||||
isInputNeuron = true;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
public ArrayList<NeuralConnection> getInputs() {
|
||||
return inputs;
|
||||
}
|
||||
|
||||
public float getBias() {
|
||||
return bias;
|
||||
}
|
||||
|
||||
public void setBias(float bias) {
|
||||
this.bias = bias;
|
||||
}
|
||||
|
||||
public boolean isIsInputNeuron() {
|
||||
return isInputNeuron;
|
||||
}
|
||||
|
||||
public int getLayer() {
|
||||
return layer;
|
||||
}
|
||||
|
||||
public void setLayer(int layer) {
|
||||
this.layer = layer;
|
||||
}
|
||||
|
||||
public void clearCachedValue() {
|
||||
cachedValueValid = false;
|
||||
for(NeuralConnection n : inputs) n.clearCachedValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user