mirror of
https://github.com/fazo96/AIrium.git
synced 2025-01-09 09:29:53 +01:00
moved from single precision floating point to double precision
This commit is contained in:
parent
7650ff44eb
commit
dd76b3acc3
@ -148,7 +148,7 @@ public class Game extends ApplicationAdapter {
|
||||
Creature c = world.getSelectedCreature();
|
||||
renderer.setColor(1, 1, 1, 1);
|
||||
// Draw selection rectangle
|
||||
renderer.rect(c.getX() - c.getSize(), c.getY() - c.getSize(), c.getSize() * 2, c.getSize() * 2);
|
||||
renderer.rect((float) (c.getX() - c.getSize()), (float) (c.getY() - c.getSize()), (float) (c.getSize() * 2), (float) (c.getSize() * 2));
|
||||
// Draw brain
|
||||
overlayRenderer.begin();
|
||||
c.getBrain().render(overlayRenderer);
|
||||
|
@ -17,9 +17,9 @@ import java.util.Random;
|
||||
public class Serializer {
|
||||
|
||||
private static final String[] sillabe = {"ba", "de", "ka", "mo", "shi", "du", "ro", "te", "mi", "lo", "pa"};
|
||||
private static Map<String, Float> defaults;
|
||||
private static Map<String, Double> defaults;
|
||||
|
||||
public static String nameBrain(float[][][] brainMap) {
|
||||
public static String nameBrain(double[][][] brainMap) {
|
||||
// Compute a unique representation of the brainmap
|
||||
long a = 0;
|
||||
for (int i = 0; i < brainMap.length; i++) {
|
||||
@ -64,19 +64,19 @@ public class Serializer {
|
||||
return a;
|
||||
}
|
||||
|
||||
public static String serializeSettings(Map<String, Float> options) {
|
||||
public static String serializeSettings(Map<String, Double> options) {
|
||||
String a = "# Settings file for use with AIrium.\n"
|
||||
+ "# More information at http://github.com/fazo96/AIrium\n";
|
||||
for (Object o : options.entrySet().toArray()) {
|
||||
Map.Entry<String, Float> e = (Map.Entry<String, Float>) o;
|
||||
Map.Entry<String, Double> e = (Map.Entry<String, Double>) o;
|
||||
a += e.getKey() + " = " + e.getValue() + "\n";
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
public static Map<String, Float> readSettings(String fileContent) {
|
||||
public static Map<String, Double> readSettings(String fileContent) {
|
||||
int line = 0;
|
||||
Map<String, Float> m = new HashMap<String, Float>();
|
||||
Map<String, Double> m = new HashMap<String, Double>();
|
||||
for (String s : fileContent.split("\n")) {
|
||||
line++;
|
||||
if (s.startsWith("#")) {
|
||||
@ -88,8 +88,8 @@ public class Serializer {
|
||||
if (ss.length != 2) {
|
||||
throw new Exception("Invalid string at line " + line);
|
||||
}
|
||||
Log.log(Log.DEBUG, "Loading setting \"" + ss[0].trim() + "\" with value \"" + Float.parseFloat(ss[1].trim()) + "\"");
|
||||
m.put(ss[0].trim(), Float.parseFloat(ss[1].trim()));
|
||||
Log.log(Log.DEBUG, "Loading setting \"" + ss[0].trim() + "\" with value \"" + Double.parseDouble(ss[1].trim()) + "\"");
|
||||
m.put(ss[0].trim(), Double.parseDouble(ss[1].trim()));
|
||||
} catch (Exception e) {
|
||||
Log.log(Log.ERROR, e.getMessage());
|
||||
}
|
||||
@ -97,7 +97,7 @@ public class Serializer {
|
||||
return m;
|
||||
}
|
||||
|
||||
public static String serializeBrain(float brainMap[][][]) {
|
||||
public static String serializeBrain(double brainMap[][][]) {
|
||||
String s = "# Neural Map for use with AIrium.\n"
|
||||
+ "# More information at http://github.com/fazo96/AIrium\n"
|
||||
+ "Layers: " + (brainMap.length + 1);
|
||||
@ -116,8 +116,8 @@ public class Serializer {
|
||||
return s;
|
||||
}
|
||||
|
||||
public static float[][][] loadBrain(String s) {
|
||||
float brainMap[][][] = null;
|
||||
public static double[][][] loadBrain(String s) {
|
||||
double brainMap[][][] = null;
|
||||
Log.log(Log.INFO, "Loading brain from String with " + s.split("\n").length + " lines");
|
||||
for (String l : s.split("\n")) {
|
||||
l = l.trim();
|
||||
@ -126,25 +126,25 @@ public class Serializer {
|
||||
} else if (l.startsWith("Layers: ")) {
|
||||
// Set Layer number
|
||||
int layers = Integer.parseInt(l.split(" ")[1]) - 1;
|
||||
brainMap = new float[layers][][];
|
||||
brainMap = new double[layers][][];
|
||||
Log.log(Log.INFO, "Loaded NLayers: " + layers);
|
||||
} else if (l.startsWith("Input Neurons")) {
|
||||
int in = Integer.parseInt(l.split(" ")[2]);
|
||||
brainMap[0] = new float[in][0];
|
||||
brainMap[0] = new double[in][0];
|
||||
Log.log(Log.INFO, "Loaded NInputNeurons: " + in);
|
||||
} else if (l.startsWith("Layer ")) {
|
||||
// Set neuron number for given layer
|
||||
String ll[] = l.split(" ");
|
||||
int layer = Integer.parseInt(ll[1]) - 2;
|
||||
int n = Integer.parseInt(ll[3]);
|
||||
brainMap[layer] = new float[n][];//[layer>0?brainMap[layer-1].length:0];
|
||||
brainMap[layer] = new double[n][];//[layer>0?brainMap[layer-1].length:0];
|
||||
} else if (l.startsWith("Weights ")) {
|
||||
// Set weights
|
||||
String ll[] = l.split(" ");
|
||||
int layer = Integer.parseInt(ll[3]) - 2;
|
||||
int neuron = Integer.parseInt(ll[5]) - 1;
|
||||
int nWeights = ll.length - 7;
|
||||
brainMap[layer][neuron] = new float[nWeights];
|
||||
brainMap[layer][neuron] = new double[nWeights];
|
||||
if (layer == 0) {
|
||||
Log.log(Log.DEBUG, "This weightmap is for brains with " + (nWeights) + " input neurons.");
|
||||
} else if (nWeights != brainMap[layer - 1].length) {
|
||||
@ -154,7 +154,7 @@ public class Serializer {
|
||||
+ " weights are supplied to this neuron");
|
||||
}
|
||||
for (int i = 7; i < ll.length; i++) {
|
||||
brainMap[layer][neuron][i - 7] = Float.parseFloat(ll[i]);
|
||||
brainMap[layer][neuron][i - 7] = Double.parseDouble(ll[i]);
|
||||
Log.log(Log.DEBUG, "Loading L" + layer + "N" + neuron + "W" + (i - 7) + " = " + brainMap[layer][neuron][i - 7]);
|
||||
}
|
||||
Log.log(Log.DEBUG, "Loaded " + (nWeights) + " Weights for Layer " + layer + " Neuron " + neuron);
|
||||
@ -164,7 +164,7 @@ public class Serializer {
|
||||
return brainMap;
|
||||
}
|
||||
|
||||
public static Map<String, Float> getDefaultSettings() {
|
||||
public static Map<String, Double> getDefaultSettings() {
|
||||
if (defaults == null) {
|
||||
String s = "corpse_decay_rate = 0.0\n"
|
||||
+ "mutationFactor = 1.0\n"
|
||||
|
@ -9,7 +9,7 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
*/
|
||||
public abstract class Element {
|
||||
|
||||
private float x, y, size;
|
||||
private double x, y, size;
|
||||
|
||||
/**
|
||||
* Create an element at given position with given radius. Elements have a
|
||||
@ -19,7 +19,7 @@ public abstract class Element {
|
||||
* @param y the y position
|
||||
* @param size the element body radius
|
||||
*/
|
||||
public Element(float x, float y, float size) {
|
||||
public Element(double x, double y, double size) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.size = size;
|
||||
@ -35,8 +35,8 @@ public abstract class Element {
|
||||
* @return the distance from the element. It's 0 if they are just touching,
|
||||
* negative if they are colliding and positive if they are not
|
||||
*/
|
||||
public float distanceFrom(Element e) {
|
||||
return (float) Math.sqrt(Math.pow(e.x - x, 2) + Math.pow(e.y - y, 2)) - getSize() - e.getSize();
|
||||
public double distanceFrom(Element e) {
|
||||
return Math.sqrt(Math.pow(e.x - x, 2) + Math.pow(e.y - y, 2)) - getSize() - e.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,8 +58,8 @@ public abstract class Element {
|
||||
* @param radius the radius of the circular object
|
||||
* @return true if the object overlaps this one
|
||||
*/
|
||||
public boolean overlaps(float x, float y, float radius) {
|
||||
return (float) Math.sqrt(Math.pow(x - this.x, 2) + Math.pow(y - this.y, 2)) < getSize() + radius;
|
||||
public boolean overlaps(double x, double y, double radius) {
|
||||
return Math.sqrt(Math.pow(x - this.x, 2) + Math.pow(y - this.y, 2)) < getSize() + radius;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,7 +69,7 @@ public abstract class Element {
|
||||
* @param y the y position of the point to check
|
||||
* @return true if the point is part of this object's area
|
||||
*/
|
||||
public boolean overlaps(float x, float y) {
|
||||
public boolean overlaps(double x, double y) {
|
||||
return overlaps(x, y, 1);
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ public abstract class Element {
|
||||
* @param deltaX x translation
|
||||
* @param deltaY y translation
|
||||
*/
|
||||
public void move(float deltaX, float deltaY) {
|
||||
public void move(double deltaX, double deltaY) {
|
||||
x += deltaX;
|
||||
y += deltaY;
|
||||
}
|
||||
@ -96,27 +96,27 @@ public abstract class Element {
|
||||
*/
|
||||
public abstract void render(ShapeRenderer s);
|
||||
|
||||
public float getX() {
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public float getY() {
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public float getSize() {
|
||||
public double getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setX(float x) {
|
||||
public void setX(double x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public void setY(float y) {
|
||||
public void setY(double y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public void setSize(float size) {
|
||||
public void setSize(double size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
|
@ -9,10 +9,10 @@ import com.mygdx.game.Game;
|
||||
*/
|
||||
public class Vegetable extends Element {
|
||||
|
||||
public static float default_radius = 5;
|
||||
private float decayRate = 0;
|
||||
public static double default_radius = 5;
|
||||
private double decayRate = 0;
|
||||
|
||||
public Vegetable(float x, float y) {
|
||||
public Vegetable(double x, double y) {
|
||||
super(x, y, default_radius);
|
||||
}
|
||||
|
||||
@ -27,14 +27,14 @@ public class Vegetable extends Element {
|
||||
@Override
|
||||
public void render(ShapeRenderer s) {
|
||||
s.setColor(1, 1, 1, 1);
|
||||
s.circle(getX(), getY(), getSize());
|
||||
s.circle((float) getX(), (float) getY(), (float) getSize());
|
||||
}
|
||||
|
||||
public float getDecayRate() {
|
||||
public double getDecayRate() {
|
||||
return decayRate;
|
||||
}
|
||||
|
||||
public void setDecayRate(float decayRate) {
|
||||
public void setDecayRate(double decayRate) {
|
||||
this.decayRate = decayRate;
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,11 @@ import logic.neural.Brain;
|
||||
public class World implements Runnable {
|
||||
|
||||
private int width, height, nPlants, creatPerGen;
|
||||
private float nMutatedBrains = 0.2f, nMutatedNeurons = 0.5f, nMutatedConnections = 0.5f, mutationFactor = 1f;
|
||||
private double nMutatedBrains = 0.2f, nMutatedNeurons = 0.5f, nMutatedConnections = 0.5f, mutationFactor = 1f;
|
||||
private int generation = 1;
|
||||
private boolean multithreading, cmdLaunchNewGen = false, cmdRestart = false;
|
||||
private int fpsLimit, fps = 0;
|
||||
private Map<String, Float> options;
|
||||
private Map<String, Double> options;
|
||||
private long ticksSinceGenStart = 0, maximumTicksPerGen = 0;
|
||||
private Creature selected;
|
||||
private Queue<Integer> events = new LinkedList<>();
|
||||
@ -52,9 +52,9 @@ public class World implements Runnable {
|
||||
* @param options customization options. Can be null. See the
|
||||
* "reloadOptions" function for possible options
|
||||
*/
|
||||
public World(Map<String, Float> options) {
|
||||
public World(Map<String, Double> options) {
|
||||
if (options == null) {
|
||||
this.options = new HashMap<String, Float>();
|
||||
this.options = new HashMap<String, Double>();
|
||||
} else {
|
||||
this.options = options;
|
||||
}
|
||||
@ -224,7 +224,7 @@ public class World implements Runnable {
|
||||
}
|
||||
Creature[] top = new Creature[topSize];
|
||||
// Calculate avg fitness and prepare best agent list
|
||||
float avgFitness = 0;
|
||||
double avgFitness = 0;
|
||||
for (int i = 0; i < graveyard.size(); i++) {
|
||||
Creature c = graveyard.get(i);
|
||||
if (i < topSize) {
|
||||
@ -243,7 +243,7 @@ public class World implements Runnable {
|
||||
while (sec == first && topSize > 1) {
|
||||
sec = (int) Math.floor(Math.random() * topSize);
|
||||
}
|
||||
float[][][] n = null;
|
||||
double[][][] n = null;
|
||||
try {
|
||||
n = top[first].getBrain().breed(top[sec].getBrain().getMap());
|
||||
} catch (Exception ex) {
|
||||
@ -274,15 +274,15 @@ public class World implements Runnable {
|
||||
*/
|
||||
public void reloadOptions() {
|
||||
for (Object o : Serializer.getDefaultSettings().entrySet().toArray()) {
|
||||
Map.Entry<String, Float> e = (Map.Entry<String, Float>) o;
|
||||
Map.Entry<String, Double> e = (Map.Entry<String, Double>) o;
|
||||
options.putIfAbsent(e.getKey(), e.getValue());
|
||||
}
|
||||
width = Math.round(options.get("world_width"));
|
||||
height = Math.round(options.get("world_height"));
|
||||
fpsLimit = Math.round(options.get("fps_limit"));
|
||||
width = (int) Math.round(options.get("world_width"));
|
||||
height = (int) Math.round(options.get("world_height"));
|
||||
fpsLimit = (int) Math.round(options.get("fps_limit"));
|
||||
maximumTicksPerGen = Math.round(options.get("max_ticks"));
|
||||
creatPerGen = Math.round(options.get("number_of_creatures"));
|
||||
nPlants = Math.round(options.get("number_of_plants"));
|
||||
creatPerGen = (int) Math.round(options.get("number_of_creatures"));
|
||||
nPlants = (int) Math.round(options.get("number_of_plants"));
|
||||
multithreading = options.get("enable_multithreading") > 0;
|
||||
Creature.corpseDecayRate = options.get("corpse_decay_rate");
|
||||
Creature.leaveCorpses = options.get("enable_corpses") > 0;
|
||||
@ -297,8 +297,8 @@ public class World implements Runnable {
|
||||
Creature.hpForEatingPlants = options.get("creature_hp_for_eating_plants");
|
||||
Creature.pointsForAttacking = options.get("creature_points_for_attacking");
|
||||
Creature.pointsForEatingPlants = options.get("creature_points_for_eating_plants");
|
||||
Creature.brain_hidden_layers = Math.round(options.get("brain_hidden_layers"));
|
||||
Creature.brain_hidden_neurons = Math.round(options.get("brain_hidden_neurons"));
|
||||
Creature.brain_hidden_layers = (int) Math.round(options.get("brain_hidden_layers"));
|
||||
Creature.brain_hidden_neurons = (int) Math.round(options.get("brain_hidden_neurons"));
|
||||
Brain.bias = options.get("brain_bias");
|
||||
nMutatedBrains = options.get("nMutatedBrains");
|
||||
nMutatedNeurons = options.get("nMutatedNeurons");
|
||||
@ -314,9 +314,9 @@ public class World implements Runnable {
|
||||
* null, a random mind will be created
|
||||
* @return the spawned element
|
||||
*/
|
||||
private Element spawn(boolean isCreature, float[][][] brainMap) {
|
||||
private Element spawn(boolean isCreature, double[][][] brainMap) {
|
||||
int x, y;
|
||||
float r;
|
||||
double r;
|
||||
boolean overlaps;
|
||||
if (isCreature) {
|
||||
r = Torso.default_radius;
|
||||
@ -394,10 +394,10 @@ public class World implements Runnable {
|
||||
events.add(eventCode);
|
||||
}
|
||||
|
||||
public Queue<Integer> getEventQueue(){
|
||||
public Queue<Integer> getEventQueue() {
|
||||
return events;
|
||||
}
|
||||
|
||||
|
||||
public void spawnVegetable() {
|
||||
spawn(false, null);
|
||||
}
|
||||
@ -406,7 +406,7 @@ public class World implements Runnable {
|
||||
return (Creature) spawn(true, null);
|
||||
}
|
||||
|
||||
public Creature spawnCreature(float[][][] b) {
|
||||
public Creature spawnCreature(double[][][] b) {
|
||||
return (Creature) spawn(true, b);
|
||||
}
|
||||
|
||||
@ -446,7 +446,7 @@ public class World implements Runnable {
|
||||
return plants;
|
||||
}
|
||||
|
||||
public float getFpsLimit() {
|
||||
public double getFpsLimit() {
|
||||
return fpsLimit;
|
||||
}
|
||||
|
||||
@ -454,11 +454,11 @@ public class World implements Runnable {
|
||||
this.fpsLimit = fpsLimit;
|
||||
}
|
||||
|
||||
public float getFps() {
|
||||
public double getFps() {
|
||||
return fps;
|
||||
}
|
||||
|
||||
public Map<String, Float> getOptions() {
|
||||
public Map<String, Double> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
@ -478,7 +478,7 @@ public class World implements Runnable {
|
||||
this.multithreading = multithreading;
|
||||
}
|
||||
|
||||
public void replaceOptions(Map<String, Float> options) {
|
||||
public void replaceOptions(Map<String, Double> options) {
|
||||
this.options = options;
|
||||
reloadOptions();
|
||||
}
|
||||
|
@ -14,18 +14,18 @@ import logic.Element;
|
||||
*/
|
||||
public class Beak extends BodyPart {
|
||||
|
||||
private float length;
|
||||
private double length;
|
||||
private boolean attacking = false;
|
||||
public static float max_length = Torso.default_radius / 4, min_length = max_length / 4;
|
||||
public static double max_length = Torso.default_radius / 4, min_length = max_length / 4;
|
||||
|
||||
public Beak(float angle, Creature creature) {
|
||||
public Beak(double angle, Creature creature) {
|
||||
super(3, 1, angle, 1, creature);
|
||||
length = min_length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] act() {
|
||||
float r[] = new float[]{
|
||||
public double[] act() {
|
||||
double r[] = new double[]{
|
||||
length / max_length, // current beak length
|
||||
length > max_length / 2 ? 1f : 0f, // wether the beak is doing damage
|
||||
attacking ? 1f : 0f
|
||||
@ -35,7 +35,7 @@ public class Beak extends BodyPart {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interactWithElement(Element e, float distance, float relAngle) {
|
||||
public void interactWithElement(Element e, double distance, double relAngle) {
|
||||
if (e instanceof Creature && distance < length && length > max_length / 2 && Math.abs(relAngle) < 0.3f) {
|
||||
// Can attack
|
||||
creature.praise(Creature.pointsForAttacking);
|
||||
@ -46,10 +46,10 @@ public class Beak extends BodyPart {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void draw(ShapeRenderer s, float relX, float relY) {
|
||||
protected void draw(ShapeRenderer s, double relX, double relY) {
|
||||
s.set(ShapeRenderer.ShapeType.Line);
|
||||
// Draw Beak
|
||||
s.setColor(getLength() / Beak.max_length, 1 - getLength() / Beak.max_length, 0, 1);
|
||||
s.setColor((float) (getLength() / Beak.max_length), (float) (1 - getLength() / Beak.max_length), 0, 1);
|
||||
s.line((float) (relX + creature.getX()), (float) (relY + creature.getY()), (float) (relX * (1.5f + getLength() / Beak.max_length) + creature.getX()), (float) (relY * (1.5f + getLength() / Beak.max_length) + creature.getY()));
|
||||
if (attacking) {
|
||||
s.circle((float) (relX * (1.5f + getLength() / Beak.max_length) + creature.getX()), (float) (relY * (1.5f + getLength() / Beak.max_length) + creature.getY()), 0.3f);
|
||||
@ -57,7 +57,7 @@ public class Beak extends BodyPart {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromBrain(float[] outputs) {
|
||||
public void readFromBrain(double[] outputs) {
|
||||
length = outputs[0] * max_length;
|
||||
if (length > max_length) {
|
||||
length = max_length;
|
||||
@ -66,7 +66,7 @@ public class Beak extends BodyPart {
|
||||
}
|
||||
}
|
||||
|
||||
public float getLength() {
|
||||
public double getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,8 @@ import logic.Element;
|
||||
public abstract class BodyPart {
|
||||
|
||||
protected int inputNeuronsUsed;
|
||||
protected float angle, distFromCenter;
|
||||
protected float outputs[];
|
||||
protected double angle, distFromCenter;
|
||||
protected double outputs[];
|
||||
protected Creature creature;
|
||||
|
||||
/**
|
||||
@ -26,12 +26,12 @@ public abstract class BodyPart {
|
||||
* this body part
|
||||
* @param creature the creature that owns this body part
|
||||
*/
|
||||
public BodyPart(int inputNeuronsUsed, int outputNeuronsUsed, float angle, float distFromCenter, Creature creature) {
|
||||
public BodyPart(int inputNeuronsUsed, int outputNeuronsUsed, double angle, double distFromCenter, Creature creature) {
|
||||
this.inputNeuronsUsed = inputNeuronsUsed;
|
||||
this.angle = angle;
|
||||
this.distFromCenter = distFromCenter;
|
||||
this.creature = creature;
|
||||
outputs = new float[outputNeuronsUsed];
|
||||
outputs = new double[outputNeuronsUsed];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -40,7 +40,7 @@ public abstract class BodyPart {
|
||||
*
|
||||
* @return the data to send to the brain, must be inputNeuronsUsed long
|
||||
*/
|
||||
public abstract float[] act();
|
||||
public abstract double[] act();
|
||||
|
||||
/**
|
||||
* Interact with another element. This will be called every time the body
|
||||
@ -52,7 +52,7 @@ public abstract class BodyPart {
|
||||
* @param distance the distance
|
||||
* @param relAngle the relative angle
|
||||
*/
|
||||
public abstract void interactWithElement(Element e, float distance, float relAngle);
|
||||
public abstract void interactWithElement(Element e, double distance, double relAngle);
|
||||
|
||||
/**
|
||||
* Receive some data from the brain. This is called once every frame, after
|
||||
@ -61,7 +61,7 @@ public abstract class BodyPart {
|
||||
* @param data the data received from the brain, will be outputNeuronsUsed
|
||||
* long
|
||||
*/
|
||||
public abstract void readFromBrain(float data[]);
|
||||
public abstract void readFromBrain(double data[]);
|
||||
|
||||
/**
|
||||
* This will be called when the
|
||||
@ -72,7 +72,7 @@ public abstract class BodyPart {
|
||||
* @param relY the Y position of this bodypart relative to the center its
|
||||
* creature
|
||||
*/
|
||||
protected abstract void draw(ShapeRenderer s, float relX, float relY);
|
||||
protected abstract void draw(ShapeRenderer s, double relX, double relY);
|
||||
|
||||
/**
|
||||
* Prepares data and calls draw
|
||||
@ -82,7 +82,7 @@ public abstract class BodyPart {
|
||||
public final void render(ShapeRenderer s) {
|
||||
double relX = Math.cos(creature.getDirection() + angle) * creature.getTorso().getRadius() * distFromCenter;
|
||||
double relY = Math.sin(creature.getDirection() + angle) * creature.getTorso().getRadius() * distFromCenter;
|
||||
draw(s, (float) relX, (float) relY);
|
||||
draw(s, (double) relX, (double) relY);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,11 +105,11 @@ public abstract class BodyPart {
|
||||
*
|
||||
* @return the angle of this bodypart relative to the center of the creature
|
||||
*/
|
||||
public float getAngle() {
|
||||
public double getAngle() {
|
||||
return angle;
|
||||
}
|
||||
|
||||
public float getDistanceFromCreatureCenter() {
|
||||
public double getDistanceFromCreatureCenter() {
|
||||
return distFromCenter;
|
||||
}
|
||||
|
||||
|
@ -20,13 +20,13 @@ import logic.neural.Brain;
|
||||
public abstract class Creature extends Element implements Runnable {
|
||||
|
||||
public static int brain_hidden_layers = 2, brain_hidden_neurons = 10;
|
||||
public static float corpseDecayRate = 0, pointsForEatingPlants = 1f, pointsForAttacking = 2f, hpForAttacking = 1f, hpForEatingPlants = 1f;
|
||||
public static double corpseDecayRate = 0, pointsForEatingPlants = 1f, pointsForAttacking = 2f, hpForAttacking = 1f, hpForEatingPlants = 1f;
|
||||
public static boolean leaveCorpses = false;
|
||||
|
||||
private final Brain brain;
|
||||
private final Torso torso;
|
||||
private final ArrayList<BodyPart> bodyParts;
|
||||
private float dir, fitness = 0;
|
||||
private double dir, fitness = 0;
|
||||
private boolean workerDone = false, killWorker = false;
|
||||
private Thread workerThread;
|
||||
|
||||
@ -36,9 +36,9 @@ public abstract class Creature extends Element implements Runnable {
|
||||
* @param x
|
||||
* @param y
|
||||
*/
|
||||
public Creature(float x, float y) {
|
||||
public Creature(double x, double y) {
|
||||
super(x, y, Torso.default_radius);
|
||||
dir = (float) (Math.random() * 2 * Math.PI);
|
||||
dir = (double) (Math.random() * 2 * Math.PI);
|
||||
bodyParts = new ArrayList<BodyPart>();
|
||||
bodyParts.add(torso = new Torso(this));
|
||||
buildBody();
|
||||
@ -77,10 +77,10 @@ public abstract class Creature extends Element implements Runnable {
|
||||
return;
|
||||
}
|
||||
// collect inputs
|
||||
float values[] = new float[howManyInputNeurons()];
|
||||
double values[] = new double[howManyInputNeurons()];
|
||||
int i = 0;
|
||||
for (BodyPart b : bodyParts) {
|
||||
for (float v : b.act()) {
|
||||
for (double v : b.act()) {
|
||||
values[i] = v;
|
||||
i++;
|
||||
}
|
||||
@ -88,7 +88,7 @@ public abstract class Creature extends Element implements Runnable {
|
||||
// read from sensors and interact with world
|
||||
interactWithWorld();
|
||||
// compute behavior
|
||||
float[] actions = null;
|
||||
double[] actions = null;
|
||||
try {
|
||||
actions = brain.compute(values);
|
||||
} catch (Exception ex) {
|
||||
@ -99,7 +99,7 @@ public abstract class Creature extends Element implements Runnable {
|
||||
// Save brain outputs to body parts
|
||||
for (BodyPart b : bodyParts) {
|
||||
int n = 0;
|
||||
float data[] = new float[b.getOutputNeuronsUsed()];
|
||||
double data[] = new double[b.getOutputNeuronsUsed()];
|
||||
while (n < b.getOutputNeuronsUsed()) {
|
||||
data[n] = actions[i];
|
||||
i++;
|
||||
@ -122,8 +122,8 @@ public abstract class Creature extends Element implements Runnable {
|
||||
*/
|
||||
public void interactWithWorld() {
|
||||
for (Element e : Game.get().getWorld().getElements()) {
|
||||
float distance = distanceFrom(e);
|
||||
float angle = (float) (Math.atan2(getY() - e.getY(), getX() - e.getX())) - (dir - (float) Math.PI);
|
||||
double distance = distanceFrom(e);
|
||||
double angle = (double) (Math.atan2(getY() - e.getY(), getX() - e.getX())) - (dir - (double) Math.PI);
|
||||
for (BodyPart b : bodyParts) {
|
||||
b.interactWithElement(e, distance, angle);
|
||||
}
|
||||
@ -146,7 +146,7 @@ public abstract class Creature extends Element implements Runnable {
|
||||
return n;
|
||||
}
|
||||
|
||||
public void rotate(float amount) {
|
||||
public void rotate(double amount) {
|
||||
dir += amount;
|
||||
if (dir > 2 * Math.PI) {
|
||||
dir -= 2 * Math.PI;
|
||||
@ -161,7 +161,7 @@ public abstract class Creature extends Element implements Runnable {
|
||||
*
|
||||
* @param amount how much
|
||||
*/
|
||||
public void praise(float amount) {
|
||||
public void praise(double amount) {
|
||||
fitness += amount;
|
||||
}
|
||||
|
||||
@ -189,9 +189,9 @@ public abstract class Creature extends Element implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
public float getDangerLevel() {
|
||||
public double getDangerLevel() {
|
||||
int beaks = 0;
|
||||
float danger = 0;
|
||||
double danger = 0;
|
||||
for (BodyPart b : bodyParts) {
|
||||
if (b instanceof Beak) {
|
||||
beaks++;
|
||||
@ -217,15 +217,15 @@ public abstract class Creature extends Element implements Runnable {
|
||||
return brain;
|
||||
}
|
||||
|
||||
public void setDirection(float dir) {
|
||||
public void setDirection(double dir) {
|
||||
this.dir = dir;
|
||||
}
|
||||
|
||||
public float getDirection() {
|
||||
public double getDirection() {
|
||||
return dir;
|
||||
}
|
||||
|
||||
public float getFitness() {
|
||||
public double getFitness() {
|
||||
return fitness;
|
||||
}
|
||||
|
||||
|
@ -19,18 +19,18 @@ public class Eye extends BodyPart {
|
||||
|
||||
private Sight sights[];
|
||||
private int farthest = -1, seen;
|
||||
private float farthestDistance = 0;
|
||||
public static float fov = 2, sightRange = 30;
|
||||
private double farthestDistance = 0;
|
||||
public static double fov = 2, sightRange = 30;
|
||||
|
||||
public Eye(int nSights, float angle, Creature creature) {
|
||||
public Eye(int nSights, double angle, Creature creature) {
|
||||
super(6 * nSights, 0, angle, 0.8f, creature);
|
||||
sights = new Sight[nSights];
|
||||
seen = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] act() {
|
||||
float ret[] = new float[inputNeuronsUsed];
|
||||
public double[] act() {
|
||||
double ret[] = new double[inputNeuronsUsed];
|
||||
int j = 0;
|
||||
for (int i = 0; i < sights.length; i++) {
|
||||
if (i < seen) {
|
||||
@ -62,7 +62,7 @@ public class Eye extends BodyPart {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interactWithElement(Element e, float distance, float angle) {
|
||||
public void interactWithElement(Element e, double distance, double angle) {
|
||||
if (e != creature && distance < sightRange && (distance < farthestDistance || seen < sights.length) && Math.abs(angle) < fov / 2) {
|
||||
if (seen < sights.length) {
|
||||
sights[seen] = new Sight(e, distance, angle);
|
||||
@ -85,36 +85,36 @@ public class Eye extends BodyPart {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void draw(ShapeRenderer s, float relX, float relY) {
|
||||
protected void draw(ShapeRenderer s, double relX, double relY) {
|
||||
// Draw eye
|
||||
s.setColor(1, 1, 1, 1);
|
||||
s.circle(creature.getX() + relX, creature.getY() + relY, 3);
|
||||
s.circle((float) (creature.getX() + relX), (float) (creature.getY() + relY), 3);
|
||||
// Draw FOV cone
|
||||
float degrees = fov * 360f / (float) Math.PI;
|
||||
float orient = (creature.getDirection() + angle) * 180f / (float) Math.PI - degrees / 2;
|
||||
if (Game.get().getWorld().getOptions().getOrDefault("draw_view_cones", 0f) > 0) {
|
||||
double degrees = fov * 360f / (double) Math.PI;
|
||||
double orient = (creature.getDirection() + angle) * 180f / (double) Math.PI - degrees / 2;
|
||||
if (Game.get().getWorld().getOptions().getOrDefault("draw_view_cones", 0d) > 0) {
|
||||
s.setColor(0.3f, 0.3f, 0.3f, 1);
|
||||
s.arc((float) relX + creature.getX(), (float) relY + creature.getY(), sightRange, orient, degrees);
|
||||
s.arc((float) (relX + creature.getX()), (float) (relY + creature.getY()), (float) sightRange, (float) orient, (float) degrees);
|
||||
}
|
||||
// Sight Lines
|
||||
float c = 0;
|
||||
if (Game.get().getWorld().getOptions().getOrDefault("draw_sight_lines", 0f) > 0) {
|
||||
double c = 0;
|
||||
if (Game.get().getWorld().getOptions().getOrDefault("draw_sight_lines", 0d) > 0) {
|
||||
for (Sight sight : sights) {
|
||||
if (sight != null) {
|
||||
c = sight.getDistance() / sightRange * 2 + sightRange;
|
||||
if (sight.getElement() instanceof Creature) {
|
||||
s.setColor(c, 0, 0, 1);
|
||||
s.setColor((float) c, 0, 0, 1);
|
||||
} else if (sight.getElement() instanceof Vegetable) {
|
||||
s.setColor(0, c, 0, 1);
|
||||
s.setColor(0, (float) c, 0, 1);
|
||||
}
|
||||
s.line(relX + creature.getX(), creature.getY() + relY, sight.getElement().getX(), sight.getElement().getY());
|
||||
s.line((float) (relX + creature.getX()), (float) (creature.getY() + relY), (float) (sight.getElement().getX()), (float) (sight.getElement().getY()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromBrain(float[] data) {
|
||||
public void readFromBrain(double[] data) {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,15 +16,15 @@ import logic.Element;
|
||||
*/
|
||||
public class Movement extends BodyPart {
|
||||
|
||||
private float speed = 0, rotSpeed = 0;
|
||||
public static float max_speed = 3;
|
||||
private double speed = 0, rotSpeed = 0;
|
||||
public static double max_speed = 3;
|
||||
|
||||
public Movement(Creature creature) {
|
||||
super(0, 4, 0, 0, creature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] act() {
|
||||
public double[] act() {
|
||||
if (speed > max_speed) {
|
||||
speed = max_speed;
|
||||
}
|
||||
@ -32,7 +32,7 @@ public class Movement extends BodyPart {
|
||||
speed = -max_speed;
|
||||
}
|
||||
// apply speed
|
||||
float xMul = (float) Math.cos(creature.getDirection()), yMul = (float) Math.sin(creature.getDirection());
|
||||
double xMul = (double) Math.cos(creature.getDirection()), yMul = (double) Math.sin(creature.getDirection());
|
||||
creature.move(xMul * speed, yMul * speed);
|
||||
if (creature.getX() < 0) {
|
||||
creature.setX(Game.get().getWorld().getWidth() + creature.getX());
|
||||
@ -45,19 +45,19 @@ public class Movement extends BodyPart {
|
||||
creature.setY(creature.getY() - Game.get().getWorld().getHeight());
|
||||
}
|
||||
creature.rotate(rotSpeed);
|
||||
return new float[]{};
|
||||
return new double[]{};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interactWithElement(Element e, float distance, float relAngle) {
|
||||
public void interactWithElement(Element e, double distance, double relAngle) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void draw(ShapeRenderer s, float relX, float relY) {
|
||||
protected void draw(ShapeRenderer s, double relX, double relY) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromBrain(float[] data) {
|
||||
public void readFromBrain(double[] data) {
|
||||
Log.log(Log.DEBUG, "Fowward: " + data[0] + "Back: " + data[1] + " Rot: " + data[2] + " RotAnti: " + data[3]);
|
||||
speed = (data[0] * 2 - data[1] / 2) * max_speed;
|
||||
rotSpeed = data[2] - data[3];
|
||||
|
@ -10,9 +10,9 @@ import logic.Element;
|
||||
public class Sight {
|
||||
|
||||
private Element seen;
|
||||
private float distance, angle;
|
||||
private double distance, angle;
|
||||
|
||||
public Sight(Element seen, float distance, float angle) {
|
||||
public Sight(Element seen, double distance, double angle) {
|
||||
this.seen = seen;
|
||||
this.distance = distance;
|
||||
this.angle = angle;
|
||||
@ -22,11 +22,11 @@ public class Sight {
|
||||
return seen;
|
||||
}
|
||||
|
||||
public float getDistance() {
|
||||
public double getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public float getAngle() {
|
||||
public double getAngle() {
|
||||
return angle;
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,8 @@ import logic.Vegetable;
|
||||
*/
|
||||
public class Torso extends BodyPart {
|
||||
|
||||
private float hp, prevHp, radius, pain = 0;
|
||||
public static float default_radius = 20, max_hp = 100, hpDecay = 0.5f, eatingSpeed = 0.1f;
|
||||
private double hp, prevHp, radius, pain = 0;
|
||||
public static double default_radius = 20, max_hp = 100, hpDecay = 0.5f, eatingSpeed = 0.1f;
|
||||
private boolean eating = false;
|
||||
|
||||
public Torso(Creature c) {
|
||||
@ -22,9 +22,9 @@ public class Torso extends BodyPart {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(ShapeRenderer s, float x, float y) {
|
||||
s.setColor(1 - (hp / max_hp), hp / max_hp, 0, 1);
|
||||
s.circle(x + creature.getX(), y + creature.getY(), radius);
|
||||
public void draw(ShapeRenderer s, double x, double y) {
|
||||
s.setColor((float) (1 - (hp / max_hp)), (float) (hp / max_hp), 0, 1);
|
||||
s.circle((float) (x + creature.getX()), (float) (y + creature.getY()), (float) radius);
|
||||
// Draw damage/heal marks
|
||||
s.set(ShapeRenderer.ShapeType.Filled);
|
||||
if (getReceivedDamage() > 0) {
|
||||
@ -35,15 +35,15 @@ public class Torso extends BodyPart {
|
||||
s.setColor(0, 1, 0, 1);
|
||||
}
|
||||
if (getReceivedDamage() != 0 || eating) {
|
||||
s.circle(x + creature.getX(), y + creature.getY(), 5);
|
||||
s.circle((float) (x + creature.getX()), (float) (y + creature.getY()), 5);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] act() {
|
||||
public double[] act() {
|
||||
// apply hunger
|
||||
hp -= hpDecay;
|
||||
float r[] = new float[]{
|
||||
double r[] = new double[]{
|
||||
hp/max_hp,
|
||||
eating ? 1f : 0f,
|
||||
pain
|
||||
@ -55,7 +55,7 @@ public class Torso extends BodyPart {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interactWithElement(Element e, float distance, float relAngle) {
|
||||
public void interactWithElement(Element e, double distance, double relAngle) {
|
||||
if (e instanceof Vegetable && distance < 0 && hp < max_hp) {
|
||||
e.setSize(e.getSize() - eatingSpeed);
|
||||
if (e.getSize() == 0) {
|
||||
@ -68,7 +68,7 @@ public class Torso extends BodyPart {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromBrain(float[] data) {
|
||||
public void readFromBrain(double[] data) {
|
||||
if (getReceivedDamage() > 0) {
|
||||
pain = -1;
|
||||
} else if (getReceivedDamage() < 0) {
|
||||
@ -87,7 +87,7 @@ public class Torso extends BodyPart {
|
||||
*
|
||||
* @param amount how much to heal/damage
|
||||
*/
|
||||
public void heal(float amount) {
|
||||
public void heal(double amount) {
|
||||
hp += amount;
|
||||
if (hp < 0) {
|
||||
hp = 0;
|
||||
@ -97,23 +97,23 @@ public class Torso extends BodyPart {
|
||||
}
|
||||
}
|
||||
|
||||
public float getReceivedDamage() {
|
||||
public double getReceivedDamage() {
|
||||
return prevHp - hp;
|
||||
}
|
||||
|
||||
public float getRadius() {
|
||||
public double getRadius() {
|
||||
return radius;
|
||||
}
|
||||
|
||||
public void setRadius(float radius) {
|
||||
public void setRadius(double radius) {
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
public float getHp() {
|
||||
public double getHp() {
|
||||
return hp;
|
||||
}
|
||||
|
||||
public void setHp(float hp) {
|
||||
public void setHp(double hp) {
|
||||
this.hp = hp;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ import com.mygdx.game.Serializer;
|
||||
*/
|
||||
public class Brain {
|
||||
|
||||
public static float bias = 0.5f;
|
||||
public static double bias = 0.5f;
|
||||
private Neuron[][] neurons;
|
||||
private String name;
|
||||
|
||||
@ -41,7 +41,7 @@ public class Brain {
|
||||
*
|
||||
* @param brainMap the new brain map to apply
|
||||
*/
|
||||
public void remap(float[][][] brainMap) {
|
||||
public void remap(double[][][] brainMap) {
|
||||
for (int i = 0; i < brainMap.length; i++) { // for each layer (skip input)
|
||||
for (int j = 0; j < brainMap[i].length; j++) { // for each neuron
|
||||
// skip input layer
|
||||
@ -89,17 +89,17 @@ public class Brain {
|
||||
//s.set(ShapeRenderer.ShapeType.Line);
|
||||
for (int j = 0; j < neurons[i].length; j++) {
|
||||
// get neuron result first so cache system can kick in and save some calculations
|
||||
float nr = neurons[i][j].compute();
|
||||
double nr = neurons[i][j].compute();
|
||||
// Draw neuron links
|
||||
float[] links = neurons[i][j].getWeights();
|
||||
double[] links = neurons[i][j].getWeights();
|
||||
if (links != null) {
|
||||
for (int f = 0; f < links.length; f++) {
|
||||
s.setColor(links[f] < 0 ? links[f] / 2 * -1 : 0, links[f] > 0 ? links[f] / 2 : 0, 0, 1);
|
||||
s.setColor((float) (links[f] < 0 ? links[f] / 2 * -1 : 0), (float) (links[f] > 0 ? links[f] / 2 : 0), 0, 1);
|
||||
s.line(i * sepX + offset, j * sepY + offset, (i - 1) * sepX + offset, f * sepY + offset);
|
||||
}
|
||||
}
|
||||
// Draw neuron
|
||||
s.setColor(1 - nr, nr, 0, 1);
|
||||
s.setColor((float) (1 - nr), (float) nr, 0, 1);
|
||||
s.circle(i * sepX + offset, j * sepY + offset, 15);
|
||||
}
|
||||
}
|
||||
@ -113,7 +113,7 @@ public class Brain {
|
||||
* @throws Exception if the number of inputs given differs from the number
|
||||
* of input neurons of this brain
|
||||
*/
|
||||
public void input(float[] values) throws Exception {
|
||||
public void input(double[] values) throws Exception {
|
||||
if (values.length != neurons[0].length) {
|
||||
throw new Exception("Brain has " + neurons[0].length
|
||||
+ " input neurons," + " but was supplied with "
|
||||
@ -130,9 +130,9 @@ public class Brain {
|
||||
* @return an array as long as the number of output neurons, containing the
|
||||
* result
|
||||
*/
|
||||
public float[] compute() {
|
||||
public double[] compute() {
|
||||
clearCache(); // unnecessary if already called when changing inputs
|
||||
float[] res = new float[neurons[neurons.length - 1].length];
|
||||
double[] res = new double[neurons[neurons.length - 1].length];
|
||||
for (int i = 0; i < neurons[neurons.length - 1].length; i++) {
|
||||
res[i] = neurons[neurons.length - 1][i].compute();
|
||||
}
|
||||
@ -147,7 +147,7 @@ public class Brain {
|
||||
* @throws Exception if the number of inputs given differs from the number
|
||||
* of input neurons of this brain
|
||||
*/
|
||||
public float[] compute(float[] values) throws Exception {
|
||||
public double[] compute(double[] values) throws Exception {
|
||||
input(values);
|
||||
return compute();
|
||||
}
|
||||
@ -158,11 +158,11 @@ public class Brain {
|
||||
* @return a tridimensional floating point number array representing a full
|
||||
* mind
|
||||
*/
|
||||
public float[][][] getMap() {
|
||||
float[][][] res = new float[neurons.length - 1][][];
|
||||
public double[][][] getMap() {
|
||||
double[][][] res = new double[neurons.length - 1][][];
|
||||
for (int i = 1; i < neurons.length; i++) // layers (skip input layer)
|
||||
{
|
||||
res[i - 1] = new float[neurons[i].length][];
|
||||
res[i - 1] = new double[neurons[i].length][];
|
||||
for (int j = 0; j < neurons[i].length; j++) // neurons per layer
|
||||
{
|
||||
res[i - 1][j] = neurons[i][j].getWeights();
|
||||
@ -181,11 +181,11 @@ public class Brain {
|
||||
* of mutated neurons (range: from 0 to 1)
|
||||
* @return a mutated brain map of this brain's mind
|
||||
*/
|
||||
public float[][][] getMutatedMap(float mutationProbability, float connectionMutationProbability, float mutationFactor) {
|
||||
float[][][] res = new float[neurons.length - 1][][];
|
||||
public double[][][] getMutatedMap(double mutationProbability, double connectionMutationProbability, double mutationFactor) {
|
||||
double[][][] res = new double[neurons.length - 1][][];
|
||||
for (int i = 1; i < neurons.length; i++) // layers (skip input layer)
|
||||
{
|
||||
res[i - 1] = new float[neurons[i].length][];
|
||||
res[i - 1] = new double[neurons[i].length][];
|
||||
for (int j = 0; j < neurons[i].length; j++) // neurons per layer
|
||||
{
|
||||
if (Math.random() <= mutationProbability) {
|
||||
@ -205,7 +205,7 @@ public class Brain {
|
||||
* of mutated neurons (range: from 0 to 1)
|
||||
* @param mutationFactor the higher this number, the bigger the mutation
|
||||
*/
|
||||
public void mutate(float mutationProbability, float connectionMutationProbability, float mutationFactor) {
|
||||
public void mutate(double mutationProbability, double connectionMutationProbability, double 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
|
||||
@ -228,20 +228,20 @@ public class Brain {
|
||||
* @throws Exception if the brains don't have identical neuron and layer
|
||||
* numbers
|
||||
*/
|
||||
public float[][][] breed(float[][][] map) throws Exception {
|
||||
float[][][] res = new float[neurons.length - 1][][];
|
||||
public double[][][] breed(double[][][] map) throws Exception {
|
||||
double[][][] res = new double[neurons.length - 1][][];
|
||||
if (map.length != neurons.length - 1) {
|
||||
throw new Exception("incompatible brains");
|
||||
}
|
||||
for (int i = 1; i < neurons.length; i++) // layers (skip input layer)
|
||||
{
|
||||
res[i - 1] = new float[neurons[i].length][];
|
||||
res[i - 1] = new double[neurons[i].length][];
|
||||
if (map[i - 1].length != neurons[i].length) {
|
||||
throw new Exception("incompatible brains");
|
||||
}
|
||||
for (int j = 0; j < neurons[i].length; j++) // neurons per layer
|
||||
{
|
||||
res[i - 1][j] = new float[neurons[i][j].getWeights().length];
|
||||
res[i - 1][j] = new double[neurons[i][j].getWeights().length];
|
||||
if (map[i - 1][j].length != neurons[i][j].getWeights().length) {
|
||||
throw new Exception("incompatible brains");
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ import java.util.logging.Logger;
|
||||
*/
|
||||
public class Neuron {
|
||||
|
||||
private float[] weights;
|
||||
private double[] weights;
|
||||
private NeuronCache cache;
|
||||
private float bias, output;
|
||||
private double bias, output;
|
||||
private boolean isInputNeuron;
|
||||
private int layer, receivesFromLayer;
|
||||
private Brain brain;
|
||||
@ -28,7 +28,7 @@ public class Neuron {
|
||||
* neurons)
|
||||
* @param brain the brain which contains this neuron
|
||||
*/
|
||||
public Neuron(int layer, int receivesFromLayer, float bias, Brain brain) {
|
||||
public Neuron(int layer, int receivesFromLayer, double bias, Brain brain) {
|
||||
this(layer, receivesFromLayer, bias, brain, null);
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ public class Neuron {
|
||||
* @param brain the brain which contains this neuron
|
||||
* @param weights the weights to use to configure this neuron
|
||||
*/
|
||||
public Neuron(int layer, int receivesFromLayer, float bias, Brain brain, float[] weights) {
|
||||
public Neuron(int layer, int receivesFromLayer, double bias, Brain brain, double[] weights) {
|
||||
this.brain = brain;
|
||||
this.layer = layer;
|
||||
this.receivesFromLayer = receivesFromLayer;
|
||||
@ -65,14 +65,14 @@ public class Neuron {
|
||||
private void scramble() {
|
||||
// init weights
|
||||
if (layer > 0) {
|
||||
weights = new float[brain.getNeurons()[receivesFromLayer].length];
|
||||
weights = new double[brain.getNeurons()[receivesFromLayer].length];
|
||||
} else { // layer 0 or negative
|
||||
isInputNeuron = true;
|
||||
weights = new float[0];
|
||||
weights = new double[0];
|
||||
}
|
||||
// Put random weights
|
||||
for (int i = 0; i < weights.length; i++) {
|
||||
weights[i] = (float) (Math.random() * 5 - 2.5f);
|
||||
weights[i] = (double) (Math.random() * 5 - 2.5f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ public class Neuron {
|
||||
*
|
||||
* @return the output of this neuron.
|
||||
*/
|
||||
public float compute() {
|
||||
public double compute() {
|
||||
if (weights == null || weights.length == 0) {
|
||||
isInputNeuron = true;
|
||||
}
|
||||
@ -94,7 +94,7 @@ public class Neuron {
|
||||
if (cache.hasCachedOutput()) {
|
||||
return cache.getCachedOutput();
|
||||
}
|
||||
float a = bias * -1; // activation
|
||||
double a = bias * -1; // activation
|
||||
for (int i = 0; i < weights.length; i++) {
|
||||
if (cache.has(i)) {
|
||||
try {
|
||||
@ -105,13 +105,13 @@ public class Neuron {
|
||||
}
|
||||
} else {
|
||||
Neuron n = brain.getNeurons()[receivesFromLayer][i];
|
||||
float v = n.compute() * weights[i];
|
||||
double v = n.compute() * weights[i];
|
||||
a += v;
|
||||
cache.put(i, v);
|
||||
}
|
||||
}
|
||||
// sigmoid function
|
||||
float res = (float) (1 / (1 + Math.pow(Math.E, a * -1)));
|
||||
double res = (double) (1 / (1 + Math.pow(Math.E, a * -1)));
|
||||
cache.setCachedOutput(res);
|
||||
Log.log(Log.DEBUG, "Computed Value " + res + " for neuron");
|
||||
return res;
|
||||
@ -124,11 +124,11 @@ public class Neuron {
|
||||
* @param mutationFactor controls how much weights mutate
|
||||
* @return the new weights
|
||||
*/
|
||||
public float[] getMutatedWeights(float mutationProbability, float mutationFactor) {
|
||||
float[] mutatedWeights = new float[weights.length];
|
||||
public double[] getMutatedWeights(double mutationProbability, double mutationFactor) {
|
||||
double[] mutatedWeights = new double[weights.length];
|
||||
for (int i = 0; i < weights.length; i++) {
|
||||
if (Math.random() <= mutationProbability) {
|
||||
mutatedWeights[i] = weights[i] + (float) (Math.random() * mutationFactor) - mutationFactor / 2;
|
||||
mutatedWeights[i] = weights[i] + (double) (Math.random() * mutationFactor) - mutationFactor / 2;
|
||||
} else {
|
||||
mutatedWeights[i] = weights[i];
|
||||
}
|
||||
@ -141,16 +141,16 @@ public class Neuron {
|
||||
*
|
||||
* @param output the output you want to set
|
||||
*/
|
||||
public void setOutput(float output) {
|
||||
public void setOutput(double output) {
|
||||
isInputNeuron = true;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
public float getBias() {
|
||||
public double getBias() {
|
||||
return bias;
|
||||
}
|
||||
|
||||
public void setBias(float bias) {
|
||||
public void setBias(double bias) {
|
||||
this.bias = bias;
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ public class Neuron {
|
||||
this.layer = layer;
|
||||
}
|
||||
|
||||
public float[] getWeights() {
|
||||
public double[] getWeights() {
|
||||
return weights;
|
||||
}
|
||||
|
||||
@ -175,7 +175,7 @@ public class Neuron {
|
||||
*
|
||||
* @param weights the new weights to put
|
||||
*/
|
||||
public void setWeights(float[] weights) {
|
||||
public void setWeights(double[] weights) {
|
||||
this.weights = weights;
|
||||
// Changing the neuron makes the cache invalid
|
||||
clearCache();
|
||||
|
@ -7,8 +7,8 @@ package logic.neural;
|
||||
*/
|
||||
public class NeuronCache {
|
||||
|
||||
private float[] cache;
|
||||
private float cachedOutput;
|
||||
private double[] cache;
|
||||
private double cachedOutput;
|
||||
private boolean cachedOutputValid;
|
||||
private boolean[] validity;
|
||||
|
||||
@ -18,7 +18,7 @@ public class NeuronCache {
|
||||
* @param size how many inputs the requiring neuron has.
|
||||
*/
|
||||
public NeuronCache(int size) {
|
||||
cache = new float[size];
|
||||
cache = new double[size];
|
||||
validity = new boolean[size];
|
||||
clear();
|
||||
}
|
||||
@ -29,7 +29,7 @@ public class NeuronCache {
|
||||
* @param index the index of the value
|
||||
* @param value the value itself
|
||||
*/
|
||||
public void put(int index, float value) {
|
||||
public void put(int index, double value) {
|
||||
validity[index] = true;
|
||||
cache[index] = value;
|
||||
}
|
||||
@ -41,7 +41,7 @@ public class NeuronCache {
|
||||
* @return the value required
|
||||
* @throws Exception if value not stored or declared invalid
|
||||
*/
|
||||
public float get(int index) throws Exception {
|
||||
public double get(int index) throws Exception {
|
||||
if (validity[index]) {
|
||||
return cache[index];
|
||||
} else {
|
||||
@ -59,7 +59,7 @@ public class NeuronCache {
|
||||
return validity[index];
|
||||
}
|
||||
|
||||
public float getCachedOutput() {
|
||||
public double getCachedOutput() {
|
||||
return cachedOutput;
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ public class NeuronCache {
|
||||
return cachedOutputValid;
|
||||
}
|
||||
|
||||
public void setCachedOutput(float cachedOutput) {
|
||||
public void setCachedOutput(double cachedOutput) {
|
||||
this.cachedOutput = cachedOutput;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ public class GUI extends javax.swing.JFrame implements LogListener {
|
||||
private boolean shouldUpdateGUI = false;
|
||||
private final Thread guiUpdater;
|
||||
private final Listener listener;
|
||||
private Map<String, Float> options;
|
||||
private Map<String, Double> options;
|
||||
private boolean updatingSliders = false, updatingTable = false;
|
||||
|
||||
/**
|
||||
@ -67,7 +67,7 @@ public class GUI extends javax.swing.JFrame implements LogListener {
|
||||
updateGUI();
|
||||
}
|
||||
};
|
||||
options = new HashMap<String, Float>();
|
||||
options = new HashMap<String, Double>();
|
||||
world = new World(options);
|
||||
updateSettingsUI();
|
||||
settingsTable.getModel().addTableModelListener(new TableModelListener() {
|
||||
@ -965,25 +965,25 @@ public class GUI extends javax.swing.JFrame implements LogListener {
|
||||
*/
|
||||
private void saveSliderChanges() {
|
||||
if (!updatingSliders) {
|
||||
options.put("fps_limit", toggleFPSLimitCheckbox.isSelected() ? 0 : (float) fpsLimitSlider.getValue());
|
||||
options.put("enable_multithreading", multithreadingCheckbox.isSelected() ? 1f : 0f);
|
||||
options.put("number_of_creatures", (float) nCreaturesSlider.getValue());
|
||||
options.put("number_of_plants", (float) nPlantsSlider.getValue());
|
||||
options.put("corpse_decay_rate", corpseDecaySlider.getValue() / 1000f);
|
||||
options.put("enable_corpses", enableCorpsesCheckbox.isSelected() ? 1f : 0f);
|
||||
options.put("world_width", (float) worldSizeSlider.getValue());
|
||||
options.put("world_height", (float) worldSizeSlider.getValue());
|
||||
options.put("fps_limit", toggleFPSLimitCheckbox.isSelected() ? 0d : fpsLimitSlider.getValue());
|
||||
options.put("enable_multithreading", multithreadingCheckbox.isSelected() ? 1d : 0d);
|
||||
options.put("number_of_creatures", (double) nCreaturesSlider.getValue());
|
||||
options.put("number_of_plants", (double) nPlantsSlider.getValue());
|
||||
options.put("corpse_decay_rate", (double) corpseDecaySlider.getValue() / 1000d);
|
||||
options.put("enable_corpses", enableCorpsesCheckbox.isSelected() ? 1d : 0d);
|
||||
options.put("world_width", (double) worldSizeSlider.getValue());
|
||||
options.put("world_height", (double) worldSizeSlider.getValue());
|
||||
topSizeSlider.setMaximum(nCreaturesSlider.getValue());
|
||||
options.put("parents_count", (float) topSizeSlider.getValue());
|
||||
options.put("creature_sight_range", (float) sightRangeSlider.getValue());
|
||||
options.put("creature_hp_decay", (float) hpDecaySlider.getValue() / 1000);
|
||||
options.put("max_ticks", (float) maxTicksSlider.getValue());
|
||||
options.put("draw_view_cones", drawViewCones.isSelected() ? 1f : 0);
|
||||
options.put("draw_sight_lines", drawSightLines.isSelected() ? 1f : 0);
|
||||
options.put("nMutatedBrains", (float) nMutatedBrainsSlider.getValue() / 100);
|
||||
options.put("nMutatedNeurons", (float) nMutatedNeuronsSlider.getValue() / 100);
|
||||
options.put("nMutatedConnections", (float) nMutatedConnectionsSlider.getValue() / 100);
|
||||
options.put("mutationFactor", (float) mutationFactorSlider.getValue() / 100);
|
||||
options.put("parents_count", (double) topSizeSlider.getValue());
|
||||
options.put("creature_sight_range", (double) sightRangeSlider.getValue());
|
||||
options.put("creature_hp_decay", hpDecaySlider.getValue() / 1000d);
|
||||
options.put("max_ticks", (double) maxTicksSlider.getValue());
|
||||
options.put("draw_view_cones", drawViewCones.isSelected() ? 1d : 0d);
|
||||
options.put("draw_sight_lines", drawSightLines.isSelected() ? 1d : 0d);
|
||||
options.put("nMutatedBrains", nMutatedBrainsSlider.getValue() / 100d);
|
||||
options.put("nMutatedNeurons", nMutatedNeuronsSlider.getValue() / 100d);
|
||||
options.put("nMutatedConnections", nMutatedConnectionsSlider.getValue() / 100d);
|
||||
options.put("mutationFactor", mutationFactorSlider.getValue() / 100d);
|
||||
world.reloadOptions();
|
||||
}
|
||||
updateSettingsUI();
|
||||
@ -1167,7 +1167,7 @@ public class GUI extends javax.swing.JFrame implements LogListener {
|
||||
if (f == null) {
|
||||
return;
|
||||
}
|
||||
float map[][][] = Serializer.loadBrain(Serializer.loadFromFile(f));
|
||||
double map[][][] = Serializer.loadBrain(Serializer.loadFromFile(f));
|
||||
Creature c = (Creature) world.spawnCreature(map);
|
||||
world.selectCreature(c);
|
||||
updateGUI();
|
||||
@ -1213,7 +1213,7 @@ public class GUI extends javax.swing.JFrame implements LogListener {
|
||||
|
||||
private void saveTableChanges() {
|
||||
for (int row = 0; row < settingsTable.getRowCount(); row++) {
|
||||
options.put((String) settingsTable.getValueAt(row, 0), (Float) settingsTable.getValueAt(row, 1));
|
||||
options.put((String) settingsTable.getValueAt(row, 0), Double.parseDouble((String) settingsTable.getValueAt(row, 1)));
|
||||
}
|
||||
world.reloadOptions();
|
||||
updateSettingsUI();
|
||||
@ -1224,7 +1224,7 @@ public class GUI extends javax.swing.JFrame implements LogListener {
|
||||
*/
|
||||
private void updateSettingsUI() {
|
||||
updatingSliders = true;
|
||||
int fps = Math.round(options.get("fps_limit"));
|
||||
int fps = (int) Math.round(options.get("fps_limit"));
|
||||
if (fps < 1) {
|
||||
fpsLimitSlider.setValue(60);
|
||||
toggleFPSLimitCheckbox.setSelected(true);
|
||||
@ -1233,34 +1233,34 @@ public class GUI extends javax.swing.JFrame implements LogListener {
|
||||
toggleFPSLimitCheckbox.setSelected(false);
|
||||
}
|
||||
multithreadingCheckbox.setSelected(options.get("enable_multithreading") > 0f);
|
||||
nCreaturesSlider.setValue(Math.round(options.get("number_of_creatures")));
|
||||
nCreaturesSlider.setValue((int) Math.round(options.get("number_of_creatures")));
|
||||
topSizeSlider.setMaximum(nCreaturesSlider.getValue());
|
||||
topSizeSlider.setValue(Math.round(options.get("parents_count")));
|
||||
nPlantsSlider.setValue(Math.round(options.get("number_of_plants")));
|
||||
corpseDecaySlider.setValue(Math.round(options.get("corpse_decay_rate") * 1000));
|
||||
topSizeSlider.setValue((int) Math.round(options.get("parents_count")));
|
||||
nPlantsSlider.setValue((int) Math.round(options.get("number_of_plants")));
|
||||
corpseDecaySlider.setValue((int) Math.round(options.get("corpse_decay_rate") * 1000));
|
||||
enableCorpsesCheckbox.setSelected(options.get("enable_corpses") > 0f);
|
||||
worldSizeSlider.setValue(Math.round(options.get("world_height")));
|
||||
sightRangeSlider.setValue(Math.round(options.get("creature_sight_range")));
|
||||
hpDecaySlider.setValue(Math.round(options.get("creature_hp_decay") * 1000));
|
||||
maxTicksSlider.setValue(Math.round(options.get("max_ticks")));
|
||||
worldSizeSlider.setValue((int) Math.round(options.get("world_height")));
|
||||
sightRangeSlider.setValue((int) Math.round(options.get("creature_sight_range")));
|
||||
hpDecaySlider.setValue((int) Math.round(options.get("creature_hp_decay") * 1000));
|
||||
maxTicksSlider.setValue((int) Math.round(options.get("max_ticks")));
|
||||
drawViewCones.setSelected(options.get("draw_view_cones") > 0f);
|
||||
drawSightLines.setSelected(options.get("draw_sight_lines") > 0f);
|
||||
nMutatedBrainsSlider.setValue(Math.round(options.get("nMutatedBrains") * 100));
|
||||
nMutatedNeuronsSlider.setValue(Math.round(options.get("nMutatedNeurons") * 100));
|
||||
nMutatedConnectionsSlider.setValue(Math.round(options.get("nMutatedConnections") * 100));
|
||||
mutationFactorSlider.setValue(Math.round(options.get("mutationFactor") * 100));
|
||||
nMutatedBrainsSlider.setValue((int) Math.round(options.get("nMutatedBrains") * 100));
|
||||
nMutatedNeuronsSlider.setValue((int) Math.round(options.get("nMutatedNeurons") * 100));
|
||||
nMutatedConnectionsSlider.setValue((int) Math.round(options.get("nMutatedConnections") * 100));
|
||||
mutationFactorSlider.setValue((int) Math.round(options.get("mutationFactor") * 100));
|
||||
updatingSliders = false;
|
||||
currentNMutatedNeurons.setText(String.format("%.2f", (float) nMutatedNeuronsSlider.getValue() / 100) + "%");
|
||||
currentNMutatedNeurons.setText(String.format("%.2f", nMutatedNeuronsSlider.getValue() / 100d) + "%");
|
||||
currentSightRange.setText(sightRangeSlider.getValue() + "");
|
||||
currentNMutatedBrains.setText(String.format("%.2f", (float) nMutatedBrainsSlider.getValue() / 100) + "%");
|
||||
currentNMutatedBrains.setText(String.format("%.2f", nMutatedBrainsSlider.getValue() / 100d) + "%");
|
||||
currentWorldSize.setText(worldSizeSlider.getValue() + "");
|
||||
currentTopSize.setText(topSizeSlider.getValue() + (topSizeSlider.getValue() <= 0 ? " (Auto)" : ""));
|
||||
currentMaxTicks.setText(maxTicksSlider.getValue() + "");
|
||||
currentHpDecay.setText(hpDecaySlider.getValue() / 1000f + "");
|
||||
currentMutationFactor.setText(String.format("%.2f", (float) mutationFactorSlider.getValue() / 100));
|
||||
currentMutationFactor.setText(String.format("%.2f", mutationFactorSlider.getValue() / 100d));
|
||||
currentFpsLimit.setText("" + fpsLimitSlider.getValue());
|
||||
currentNCreatures.setText(nCreaturesSlider.getValue() + "");
|
||||
currentNMutatedConnections.setText(String.format("%.2f", (float) nMutatedConnectionsSlider.getValue() / 100) + "%");
|
||||
currentNMutatedConnections.setText(String.format("%.2f", nMutatedConnectionsSlider.getValue() / 100d) + "%");
|
||||
currentNPlants.setText(nPlantsSlider.getValue() + "");
|
||||
currentCorpseDecay.setText(corpseDecaySlider.getValue() / 1000f + "");
|
||||
int row = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user