1
0
mirror of https://github.com/fazo96/AIrium.git synced 2025-04-20 01:38:38 +02:00

fixed multicore, now way fast

This commit is contained in:
Enrico Fasoli 2015-07-03 21:50:49 +02:00
parent 95f03e8143
commit 93aba50c09
7 changed files with 72 additions and 62 deletions

View File

@ -17,6 +17,7 @@ public class Game extends ApplicationAdapter {
private World world;
private float cameraSpeed = 15;
private BitmapFont font;
private Thread worldThread;
private boolean paused = false;
@Override
@ -26,7 +27,10 @@ public class Game extends ApplicationAdapter {
shaper = new ShapeRenderer();
shaper.setAutoShapeType(true);
font = new BitmapFont();
new Thread(world).start();
worldThread = new Thread(world);
worldThread.setPriority(Thread.MAX_PRIORITY);
world.newGen(true);
worldThread.start();
}
@Override

View File

@ -15,7 +15,7 @@ public class Log {
public static final int INFO = 1;
public static final int DEBUG = 2;
private static int logLevel = 1;
private static int logLevel = 0;
public static void log(int level, String msg) {
if (level <= logLevel) {

View File

@ -19,7 +19,7 @@ public class Creature extends Element implements Runnable {
private Brain brain;
private float dir, hp, prevHp, speed, sightRange, fov, fitness, rotSpeed, beak;
private boolean eating = false, killing = false, done = false;
private boolean eating = false, killing = false, done = true;
private Sight[] sights;
private Thread thread;
@ -35,8 +35,6 @@ public class Creature extends Element implements Runnable {
fitness = 0;
brain = new Brain(10, 5, 2, 10);
sights = new Sight[2];
thread = new Thread(this);
thread.start();
}
@Override
@ -44,21 +42,24 @@ public class Creature extends Element implements Runnable {
for (;;) {
while (Game.get().getWorld() == null || Game.get().getWorld().isBusy()) {
/*try {
Thread.sleep(30);
} catch (InterruptedException ex) {
Logger.getLogger(Creature.class.getName()).log(Level.SEVERE, null, ex);
}*/
Thread.sleep(30);
} catch (InterruptedException ex) {
Logger.getLogger(Creature.class.getName()).log(Level.SEVERE, null, ex);
}*/
Thread.yield();
}
if (!done && !update()) {
if (done) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
//Logger.getLogger(Creature.class.getName()).log(Level.SEVERE, null, ex);
}
} else if (!update()) {
// Dead
break;
Game.get().getWorld().getGraveyard().add(this);
}
done = true;
}
done = true;
// Dead
Game.get().getWorld().getGraveyard().add(this);
}
@Override
@ -140,6 +141,9 @@ public class Creature extends Element implements Runnable {
return true;
}
/**
* Applies the creature's desired movements to the world
*/
public void applyToWorld() {
if (speed > max_speed) {
speed = max_speed;
@ -199,6 +203,11 @@ public class Creature extends Element implements Runnable {
s.arc((float) relX * getSize() + getX(), (float) relY * getSize() + getY(), sightRange, orient, degrees);
}
/**
* Reads data from sensors and applies eat/kill mechanics
*
* @return sensor data
*/
public Sight[] interactWithWorld() {
eating = false;
Sight[] sights = new Sight[2];
@ -290,6 +299,20 @@ public class Creature extends Element implements Runnable {
return sights;
}
public void resume() {
if (!done) {
Log.log(Log.ERROR, "Tried to resume running worker!");
} else {
done = false;
if (thread == null) {
thread = new Thread(this);
thread.start();
} else {
thread.interrupt();
}
}
}
public Brain getBrain() {
return brain;
}
@ -311,10 +334,6 @@ public class Creature extends Element implements Runnable {
return done;
}
public void setDone(boolean done) {
this.done = done;
}
public float getHp() {
return hp;
}

View File

@ -42,8 +42,18 @@ public abstract class Element {
y += deltaY;
}
/**
* Update element logic
*
* @return true if element is still alive
*/
public abstract boolean update();
/**
* Draw the element
*
* @param s the instance used to draw shapes
*/
public abstract void render(ShapeRenderer s);
public float getX() {

View File

@ -18,10 +18,10 @@ import java.util.logging.Logger;
*/
public class World implements Runnable {
private final Comparator<Creature> creatureComp;
private final int width, height, nPlants, creatPerGen;
private int generation = 1;
private boolean busy = true, workerDone = false;
private final Thread worker;
private boolean busy = true;
public ArrayList<Element> elements;
public ArrayList<Element> toAdd;
public ArrayList<Creature> creatures;
@ -40,28 +40,13 @@ public class World implements Runnable {
plants = new ArrayList();
deadPlants = new ArrayList();
graveyard = new ArrayList();
worker = new Thread() {
creatureComp = new Comparator<Creature>() {
@Override
public void run() {
for (;;) {
if (!workerDone) {
for (Vegetable v : plants) {
v.update();
}
workerDone = true;
} else {
Thread.yield();
/*try {
Thread.sleep(30);
} catch (InterruptedException ex) {
Logger.getLogger(World.class.getName()).log(Level.SEVERE, null, ex);
}*/
}
}
public int compare(Creature t, Creature t1) {
// put the highest fitness first (sort in reverse)
return (int) (t1.getFitness() - t.getFitness());
}
};
worker.start();
newGen(true);
}
@Override
@ -105,12 +90,14 @@ public class World implements Runnable {
while (plants.size() < nPlants) {
spawnVegetable();
}
for (Creature c : creatures) {
c.setDone(false);
for (Vegetable v : plants) {
v.update();
}
workerDone = false;
busy = false;
Log.log(Log.DEBUG, "Launching Creature workers");
for (Creature c : creatures) {
c.resume();
}
busy = false;
int readyCount = 0;
Thread.yield();
do {
@ -120,17 +107,8 @@ public class World implements Runnable {
readyCount++;
}
}
Log.log(Log.DEBUG, "DoneCount: " + readyCount + " out of " + creatures.size());
//Log.log(Log.DEBUG, "DoneCount: " + readyCount + " out of " + creatures.size());
} while (readyCount < creatures.size());
Log.log(Log.DEBUG, "Done creatures, awaiting veg worker...");
while (!workerDone) {
Thread.yield();
/*try {
Thread.sleep(30);
} catch (InterruptedException ex) {
Logger.getLogger(World.class.getName()).log(Level.SEVERE, null, ex);
}*/
}
busy = true;
Log.log(Log.DEBUG, "Paused workers. Applying modifications to world... ");
for (Creature c : creatures) {
@ -143,14 +121,6 @@ public class World implements Runnable {
elements.removeAll(creatures);
graveyard.addAll(creatures);
creatures.clear();
Comparator creatureComp = new Comparator<Creature>() {
@Override
public int compare(Creature t, Creature t1) {
// put the highest fitness first (sort in reverse)
return (int) (t1.getFitness() - t.getFitness());
}
};
if (graveyard.isEmpty() || restart) { // First gen
generation = 1;
Log.log(Log.INFO, "Starting from generation 1: spawning " + creatPerGen + " creatures.");

View File

@ -180,6 +180,13 @@ public class Brain {
}
}
/**
* Use this brain's neural map and another one to create a unique child
*
* @param map the other parent of the child
* @return a unique child mind
* @throws Exception if the brains have a different layout
*/
public float[][][] breed(float[][][] map) throws Exception {
float[][][] res = new float[neurons.length - 1][][];
if (map.length != neurons.length - 1) {

View File

@ -70,7 +70,7 @@ public class Neuron {
}
// sigmoid function
float res = (float) (1 / (1 + Math.pow(Math.E, a * -1)));
Log.log(Log.DEBUG, "Computed Value " + res + " for neuron");
//Log.log(Log.DEBUG, "Computed Value " + res + " for neuron");
return res;
}