1
0
mirror of https://github.com/fazo96/AIrium.git synced 2025-04-04 23:18:37 +02:00
AIrium/core/src/logic/World.java
2015-07-02 12:38:56 +02:00

183 lines
5.2 KiB
Java

/*
* 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;
import com.mygdx.game.Log;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.logging.Level;
import java.util.logging.Logger;
import logic.neural.Brain;
/**
*
* @author fazo
*/
public class World {
public static final int creatPerGen = 10;
private int width, height, generation = 0;
public ArrayList<Element> elements;
public ArrayList<Creature> creatures;
public ArrayList<Creature> graveyard;
public ArrayList<Vegetable> plants;
public ArrayList<Vegetable> deadPlants;
public World(int width, int height) {
this.width = width;
this.height = height;
elements = new ArrayList();
creatures = new ArrayList();
plants = new ArrayList();
deadPlants = new ArrayList();
graveyard = new ArrayList();
newGen(true);
}
public void update() {
elements.removeAll(graveyard);
elements.removeAll(deadPlants);
plants.removeAll(deadPlants);
creatures.removeAll(graveyard);
deadPlants.clear();
if (creatures.isEmpty()) {
// All dead, next gen
newGen(false);
}
while (plants.size() < 50) {
spawnVegetable();
}
for (Creature e : creatures) {
e.update();
}
}
public void newGen(boolean restart) {
elements.removeAll(creatures);
graveyard.addAll(creatures);
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 (t.getFitness() < t1.getFitness()) {
return -1;
} else if (t.getFitness() > t1.getFitness()) {
return 1;
}
return 0;*/
}
};
if (graveyard.isEmpty() || restart) { // First gen
generation = 0;
for (int i = 0; i < creatPerGen; i++) {
spawnCreature();
}
} else { // Evolve previous gen
// Calculate avg fitness
float avgFitness = 0;
for (Creature c : graveyard) {
avgFitness += c.getFitness();
}
avgFitness = avgFitness / graveyard.size();
Log.log(Log.INFO, "Gen " + generation + " done. Avg fitness: " + avgFitness);
// Start evolution
graveyard.sort(creatureComp);
for (int i = 0; i < creatPerGen / 2; i++) {
Creature c = graveyard.get(i);
c.reset();
// Mutate
if (i != 0) {
try {
// create a child
float[][][] mind = c.getBrain().breed(graveyard.get(i - 1).getBrain().getMap());
// spawn it
spawnCreature(mind);
} catch (Exception ex) {
// Should never happen
Logger.getLogger(World.class.getName()).log(Level.SEVERE, null, ex);
}
}
// Mutate parent
c.getBrain().remap(c.getBrain().getMutatedMap(0.1f));
// Add it back in
creatures.add(c);
elements.add(c);
}
graveyard.clear();
generation++;
}
}
private void spawn(boolean isCreature, float[][][] brainMap) {
int x, y, r;
boolean overlaps = false;
if (isCreature) {
r = Creature.default_radius;
} else {
r = Vegetable.default_radius;
}
do {
overlaps = false;
x = (int) (Math.random() * width);
y = (int) (Math.random() * height);
for (Element e : elements) {
if (e.overlaps(x, y, r)) {
overlaps = true;
}
}
} while (overlaps);
if (isCreature) {
Log.log(Log.INFO, "New Creat: " + x + " " + y);
Creature c = new Creature(x, y);
if (brainMap != null) {
c.getBrain().remap(brainMap);
}
elements.add(c);
creatures.add(c);
} else {
Log.log(Log.INFO, "New Veg: " + x + " " + y);
Vegetable v = new Vegetable(x, y);
elements.add(v);
plants.add(v);
}
}
private void spawnVegetable() {
spawn(false, null);
}
private void spawnCreature() {
spawn(true, null);
}
private void spawnCreature(float[][][] b) {
spawn(true, b);
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public ArrayList<Element> getElements() {
return elements;
}
public ArrayList<Creature> getGraveyard() {
return graveyard;
}
public ArrayList<Vegetable> getDeadPlants() {
return deadPlants;
}
}