diff --git a/narjillos-core/src/main/java/org/nusco/narjillos/creature/Egg.java b/narjillos-core/src/main/java/org/nusco/narjillos/creature/Egg.java index d9c3c7fb..0b1cac6f 100644 --- a/narjillos-core/src/main/java/org/nusco/narjillos/creature/Egg.java +++ b/narjillos-core/src/main/java/org/nusco/narjillos/creature/Egg.java @@ -13,7 +13,8 @@ public class Egg implements Thing { public static final double RADIUS = 25; - + public static final int INCUBATION_TIME = 500; + private final DNA dna; private int age = 0; private Vector position; diff --git a/narjillos-core/src/main/java/org/nusco/narjillos/creature/Narjillo.java b/narjillos-core/src/main/java/org/nusco/narjillos/creature/Narjillo.java index a3318927..dd64064f 100644 --- a/narjillos-core/src/main/java/org/nusco/narjillos/creature/Narjillo.java +++ b/narjillos-core/src/main/java/org/nusco/narjillos/creature/Narjillo.java @@ -11,7 +11,6 @@ import org.nusco.narjillos.shared.things.Energy; import org.nusco.narjillos.shared.things.FoodPiece; import org.nusco.narjillos.shared.things.Thing; -import org.nusco.narjillos.shared.utilities.RanGen; /** * A fully-formed, autonomous creature. @@ -19,7 +18,6 @@ public class Narjillo implements Thing { static final double MAX_LIFESPAN = 30_000; - private static final int INCUBATION_TIME = 500; private final Body body; private final DNA dna; @@ -73,16 +71,6 @@ public void feedOn(FoodPiece thing) { thing.setEater(this); } - public Egg layEgg(Vector position, RanGen ranGen) { - double percentEnergyToChildren = body.getPercentEnergyToChildren(); - double childEnergy = energy.chunkOff(percentEnergyToChildren); - if (childEnergy == 0) - return null; - - DNA childDNA = getDNA().copyWithMutations(ranGen); - return new Egg(childDNA, getPosition(), childEnergy, INCUBATION_TIME); - } - @Override public String getLabel() { return "narjillo"; diff --git a/narjillos-core/src/main/java/org/nusco/narjillos/ecosystem/Ecosystem.java b/narjillos-core/src/main/java/org/nusco/narjillos/ecosystem/Ecosystem.java index fbcc0b8f..03eafe3f 100644 --- a/narjillos-core/src/main/java/org/nusco/narjillos/ecosystem/Ecosystem.java +++ b/narjillos-core/src/main/java/org/nusco/narjillos/ecosystem/Ecosystem.java @@ -17,6 +17,7 @@ import org.nusco.narjillos.creature.Egg; import org.nusco.narjillos.creature.Narjillo; import org.nusco.narjillos.genomics.DNA; +import org.nusco.narjillos.genomics.GenePool; import org.nusco.narjillos.shared.physics.Segment; import org.nusco.narjillos.shared.physics.Vector; import org.nusco.narjillos.shared.things.FoodPiece; @@ -75,15 +76,15 @@ public Vector findClosestFoodPiece(Thing thing) { return target.getPosition(); } - public void tick(RanGen ranGen) { + public void tick(GenePool genePool, RanGen ranGen) { for (Thing thing : new LinkedList<>(things.getAll("egg"))) tickEgg((Egg) thing); for (Narjillo narjillo : new LinkedList<>(narjillos)) if (narjillo.isDead()) - removeNarjillo(narjillo); + removeNarjillo(narjillo, genePool); - tickNarjillos(ranGen); + tickNarjillos(genePool, ranGen); if (shouldSpawnFood(ranGen)) { spawnFood(randomPosition(getSize(), ranGen)); @@ -153,7 +154,7 @@ private void tickEgg(Egg egg) { remove(egg); } - private synchronized void tickNarjillos(RanGen ranGen) { + private synchronized void tickNarjillos(GenePool genePool, RanGen ranGen) { if (executorService.isShutdown()) return; // we're leaving, apparently @@ -165,7 +166,7 @@ private synchronized void tickNarjillos(RanGen ranGen) { for (Entry> entry : narjillosToCollidedFood.entrySet()) { Narjillo narjillo = entry.getKey(); Set collidedFood = entry.getValue(); - consume(narjillo, collidedFood, ranGen); + consume(narjillo, collidedFood, genePool, ranGen); } } @@ -225,12 +226,12 @@ private void updateTargets(Thing food) { } } - private void consume(Narjillo narjillo, Set foodPieces, RanGen ranGen) { + private void consume(Narjillo narjillo, Set foodPieces, GenePool genePool, RanGen ranGen) { for (Thing foodPiece : foodPieces) - consumeFood(narjillo, (FoodPiece) foodPiece, ranGen); + consumeFood(narjillo, (FoodPiece) foodPiece, genePool, ranGen); } - private void consumeFood(Narjillo narjillo, FoodPiece foodPiece, RanGen ranGen) { + private void consumeFood(Narjillo narjillo, FoodPiece foodPiece, GenePool genePool, RanGen ranGen) { if (!things.contains(foodPiece)) return; // race condition: already consumed @@ -238,7 +239,7 @@ private void consumeFood(Narjillo narjillo, FoodPiece foodPiece, RanGen ranGen) narjillo.feedOn(foodPiece); - layEgg(narjillo, ranGen); + layEgg(narjillo, genePool, ranGen); updateTargets(foodPiece); } @@ -247,16 +248,21 @@ private void remove(Thing thing) { things.remove(thing); } - private void removeNarjillo(Narjillo narjillo) { + private void removeNarjillo(Narjillo narjillo, GenePool genePool) { notifyThingRemoved(narjillo); narjillos.remove(narjillo); - narjillo.getDNA().destroy(); + genePool.remove(narjillo.getDNA()); } - private void layEgg(Narjillo narjillo, RanGen ranGen) { - Egg egg = narjillo.layEgg(narjillo.getNeckLocation(), ranGen); - if (egg == null) // refused to lay egg - return; + private void layEgg(Narjillo narjillo, GenePool genePool, RanGen ranGen) { + double percentEnergyToChildren = narjillo.getBody().getPercentEnergyToChildren(); + double childEnergy = narjillo.getEnergy().chunkOff(percentEnergyToChildren); + if (childEnergy == 0) + return; // refused to lay egg + DNA childDNA = genePool.mutateDNA(narjillo.getDNA(), ranGen); + + Vector position = narjillo.getNeckLocation(); + Egg egg = new Egg(childDNA, position, childEnergy, Egg.INCUBATION_TIME); insert(egg); } diff --git a/narjillos-core/src/main/java/org/nusco/narjillos/experiment/Experiment.java b/narjillos-core/src/main/java/org/nusco/narjillos/experiment/Experiment.java index 446baa8f..3da218fd 100644 --- a/narjillos-core/src/main/java/org/nusco/narjillos/experiment/Experiment.java +++ b/narjillos-core/src/main/java/org/nusco/narjillos/experiment/Experiment.java @@ -2,7 +2,6 @@ import org.nusco.narjillos.creature.body.physics.Viscosity; import org.nusco.narjillos.ecosystem.Ecosystem; -import org.nusco.narjillos.genomics.DNA; import org.nusco.narjillos.genomics.GenePool; import org.nusco.narjillos.shared.physics.Vector; import org.nusco.narjillos.shared.utilities.Chronometer; @@ -47,7 +46,6 @@ private void initializeGenePool(boolean trackGenePool) { return; genePool.enableTracking(); - DNA.setObserver(genePool); } public final void timeStamp() { @@ -64,10 +62,10 @@ private void populate(Ecosystem ecosystem, String dna) { if (dna == null) { for (int i = 0; i < INITIAL_NUMBER_OF_NARJILLOS; i++) - ecosystem.spawnEgg(DNA.random(ranGen), randomPosition(ecosystem.getSize()), ranGen); + ecosystem.spawnEgg(getGenePool().createRandomDNA(ranGen), randomPosition(ecosystem.getSize()), ranGen); } else { for (int i = 0; i < INITIAL_NUMBER_OF_NARJILLOS; i++) - ecosystem.spawnEgg(new DNA(dna), randomPosition(ecosystem.getSize()), ranGen); + ecosystem.spawnEgg(getGenePool().createDNA(dna), randomPosition(ecosystem.getSize()), ranGen); } } @@ -79,7 +77,7 @@ public boolean tick() { if (ticksChronometer.getTotalTicks() % 1000 == 0) executePeriodicOperations(); - getEcosystem().tick(ranGen); + getEcosystem().tick(genePool, ranGen); ticksChronometer.tick(); return areThereSurvivors(); } @@ -127,13 +125,6 @@ public GenePool getGenePool() { return genePool; } - // For serialization only. Don't call this in other situations, if you don't - // want to make the experiment non-deterministic. - public void setGenePool(GenePool genePool) { - this.genePool = genePool; - DNA.setObserver(genePool); - } - @Override public String toString() { return "Experiment " + getId(); diff --git a/narjillos-core/src/main/java/org/nusco/narjillos/genomics/DNA.java b/narjillos-core/src/main/java/org/nusco/narjillos/genomics/DNA.java index bcdda209..30271f59 100644 --- a/narjillos-core/src/main/java/org/nusco/narjillos/genomics/DNA.java +++ b/narjillos-core/src/main/java/org/nusco/narjillos/genomics/DNA.java @@ -12,44 +12,18 @@ public class DNA { public static final double MUTATION_RATE = 0.055; private static final int GENE_MUTATION_RANGE = 15; - private static DNAObserver observer = DNAObserver.NULL; - - // TODO: This static makes testing difficult. Find another way. - private static long serial = 0; - - // for testing - public static long getSerial() { - return serial; - } - - public static void setSerial(long value) { - serial = value; - } - - private long id; + private final long id; private final Integer[] genes; - public DNA(String dnaDocument) { - this(new DNADocument(dnaDocument).toGenes()); - } - - // Only use for deserialization. - public DNA(String dnaDocument, long id) { + public DNA(long id, String dnaDocument) { + this.id = id; this.genes = clipGenes(new DNADocument(dnaDocument).toGenes()); - setId(id); - } - - private DNA(Integer... genes) { - this.genes = clipGenes(genes); - setId(serial + 1); - DNA.observer.created(this, null); } - private DNA(DNA parent, Integer... genes) { + public DNA(long id, Integer[] genes) { + this.id = id; this.genes = clipGenes(genes); - setId(serial + 1); - DNA.observer.created(this, parent); } public long getId() { @@ -60,11 +34,7 @@ public Integer[] getGenes() { return genes; } - public void destroy() { - DNA.observer.removed(this); - } - - public DNA copyWithMutations(RanGen ranGen) { + public DNA copyWithMutations(long id, RanGen ranGen) { List resultChromosomes = new LinkedList<>(); DNAIterator iterator = new DNAIterator(this); @@ -79,12 +49,12 @@ public DNA copyWithMutations(RanGen ranGen) { } Integer[] resultGenes = flatten(resultChromosomes); - return new DNA(this, resultGenes); + return new DNA(id, resultGenes); } - public static DNA random(RanGen ranGen) { + public static DNA random(long id, RanGen ranGen) { int size = Chromosome.SIZE * (Math.abs(ranGen.nextInt()) % 10 + 2); - return random(size, ranGen); + return random(id, ranGen, size); } // From: http://en.wikipedia.org/wiki/Levenshtein_distance, @@ -129,10 +99,6 @@ public int getLevenshteinDistanceFrom(DNA other) { return v1[otherGenes.length]; } - public static void setObserver(DNAObserver dnaObserver) { - DNA.observer = dnaObserver; - } - @Override public int hashCode() { return (int) getId(); @@ -153,20 +119,6 @@ private Integer[] clipGenes(Integer[] genes) { return (genes.length > 0) ? clipToByteSize(genes) : new Integer[] { 0 }; } - private void setId(long id) { - this.id = id; - // This complicated mechanism guarantees that even - // after deserializing DNA, the serial will still - // contain the highest id in the system. (But - // if you generate DNA and *then* deserialize - // other DNA, then you might have duplicated - // DNA ids in the system. I assume that you - // will only deserialize DNA before ever creating - // it. - if (id > serial) - serial = id; - } - private Integer[] copyWithMutations(Chromosome chromosome, RanGen ranGen) { Integer[] result = new Integer[Chromosome.SIZE]; for (int i = 0; i < result.length; i++) @@ -210,9 +162,9 @@ private int clipToByteSize(int number) { return Math.max(0, Math.min(255, number)); } - private static DNA random(int size, RanGen ranGen) { + private static DNA random(long id, RanGen ranGen, int size) { Integer[] genes = randomGenes(size, ranGen); - return new DNA(genes); + return new DNA(id, genes); } private static Integer[] randomGenes(int size, RanGen ranGen) { diff --git a/narjillos-core/src/main/java/org/nusco/narjillos/genomics/DNAObserver.java b/narjillos-core/src/main/java/org/nusco/narjillos/genomics/DNAObserver.java deleted file mode 100644 index 1e7e2168..00000000 --- a/narjillos-core/src/main/java/org/nusco/narjillos/genomics/DNAObserver.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.nusco.narjillos.genomics; - -/** - * Observes DNA getting created and destroyed. - */ -public interface DNAObserver { - - public void created(DNA newDna, DNA parent); - public void removed(DNA dna); - - DNAObserver NULL = new DNAObserver() { - - @Override - public void created(DNA newDNA, DNA parent) { - } - - @Override - public void removed(DNA dna) { - } - }; -} diff --git a/narjillos-core/src/main/java/org/nusco/narjillos/genomics/GenePool.java b/narjillos-core/src/main/java/org/nusco/narjillos/genomics/GenePool.java index b30a3b58..ccf2bf57 100644 --- a/narjillos-core/src/main/java/org/nusco/narjillos/genomics/GenePool.java +++ b/narjillos-core/src/main/java/org/nusco/narjillos/genomics/GenePool.java @@ -6,15 +6,18 @@ import java.util.List; import java.util.Map; +import org.nusco.narjillos.shared.utilities.RanGen; + /** * A pool of DNA strands. */ -public class GenePool implements DNAObserver { +public class GenePool { - private Map dnaById = new LinkedHashMap<>(); - private List currentPool = new LinkedList<>(); - private Map childrenToParents = new LinkedHashMap<>(); + private final Map dnaById = new LinkedHashMap<>(); + private final List currentPool = new LinkedList<>(); + private final Map childrenToParents = new LinkedHashMap<>(); + private long dnaSerial = 0; private boolean isTracking = false; public void enableTracking() { @@ -25,27 +28,6 @@ public boolean isTracking() { return isTracking; } - @Override - public void created(DNA newDNA, DNA parent) { - if (!isTracking()) - return; - - dnaById.put(newDNA.getId(), newDNA); - currentPool.add(newDNA.getId()); - if (parent == null) - childrenToParents.put(newDNA.getId(), 0l); - else - childrenToParents.put(newDNA.getId(), parent.getId()); - } - - @Override - public void removed(DNA dna) { - if (!isTracking()) - return; - - currentPool.remove(dna.getId()); - } - public List getAncestry(DNA dna) { List result = new LinkedList<>(); @@ -81,6 +63,47 @@ public int getHistoricalPoolSize() { return dnaById.size(); } + public DNA createDNA(String dna) { + DNA result = new DNA(nextId(), dna); + add(result, null); + return result; + } + + public DNA createRandomDNA(RanGen ranGen) { + DNA result = DNA.random(nextId(), ranGen); + add(result, null); + return result; + } + + public DNA mutateDNA(DNA parent, RanGen ranGen) { + DNA result = parent.copyWithMutations(nextId(), ranGen); + add(result, parent); + return result; + } + + public void remove(DNA dna) { + if (!isTracking()) + return; + + currentPool.remove(dna.getId()); + } + + private long nextId() { + return ++dnaSerial; + } + + private void add(DNA dna, DNA parent) { + if (!isTracking()) + return; + + dnaById.put(dna.getId(), dna); + currentPool.add(dna.getId()); + if (parent == null) + childrenToParents.put(dna.getId(), 0l); + else + childrenToParents.put(dna.getId(), parent.getId()); + } + private int totalLevenshteinDistanceFromTheRestOfThePool(DNA dna) { int result = 0; for (Long otherDNAId : currentPool) { diff --git a/narjillos-core/src/main/java/org/nusco/narjillos/serializer/DNAAdapter.java b/narjillos-core/src/main/java/org/nusco/narjillos/serializer/DNAAdapter.java index 002cf1ef..fad96796 100644 --- a/narjillos-core/src/main/java/org/nusco/narjillos/serializer/DNAAdapter.java +++ b/narjillos-core/src/main/java/org/nusco/narjillos/serializer/DNAAdapter.java @@ -27,6 +27,6 @@ public DNA deserialize(JsonElement json, Type type, JsonDeserializationContext c JsonObject jsonObject = json.getAsJsonObject(); String genes = jsonObject.get("genes").getAsString(); long id = jsonObject.get("id").getAsLong(); - return new DNA(genes, id); + return new DNA(id, genes); } } diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/DeterministicExperimentTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/DeterministicExperimentTest.java index a3d48d12..efe27529 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/DeterministicExperimentTest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/DeterministicExperimentTest.java @@ -4,7 +4,6 @@ import org.junit.Test; import org.nusco.narjillos.experiment.Experiment; -import org.nusco.narjillos.genomics.DNA; import org.nusco.narjillos.serializer.JSON; /** @@ -42,14 +41,10 @@ public static void runTest(int cycles) { Experiment experiment2 = JSON.fromJson(json, Experiment.class); // Now we have two experiments. Keep ticking both for a few more cycles. - // Reset the DNA serial in between, so that we get the same DNA ids for - // both experiments. - long lastDNAId = DNA.getSerial(); - for (int i = 0; i < halfCycles; i++) + for (int i = 0; i < halfCycles; i++) { experiment1.tick(); - DNA.setSerial(lastDNAId); - for (int i = 0; i < halfCycles; i++) experiment2.tick(); + } // Reset the running time (which is generally different between // experiments, and that's OK). diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/NarjilloTickingTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/NarjilloTickingTest.java index ff9b891c..8ed87cd2 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/NarjilloTickingTest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/NarjilloTickingTest.java @@ -10,6 +10,7 @@ import org.nusco.narjillos.creature.body.Organ; import org.nusco.narjillos.embryogenesis.Embryo; import org.nusco.narjillos.genomics.DNA; +import org.nusco.narjillos.genomics.GenePool; import org.nusco.narjillos.serializer.JSON; import org.nusco.narjillos.shared.physics.Vector; @@ -59,9 +60,8 @@ public class NarjilloTickingTest { @Test public void narjillosTickingIsDeterministic() { - // Create DNA with an id of 1. - DNA.setSerial(0); - DNA sampleDNA = new DNA(SAMPLE_DNA_DOCUMENT); + GenePool genePool = new GenePool(); + DNA sampleDNA = genePool.createDNA(SAMPLE_DNA_DOCUMENT); // Create the sample narjillo. Narjillo narjillo = new Narjillo(sampleDNA, new Embryo(sampleDNA).develop(), Vector.cartesian(100, 200), 10_000); @@ -77,7 +77,6 @@ public void narjillosTickingIsDeterministic() { // updated at the end of the tick, even when no readers are around. narjillo.tick(); - System.out.println(JSON.toJson(narjillo, Narjillo.class)); // Check that the narjillo's state is exactly what we expect. We use // JSON to make the comparison easier, and also to make sure that we're // not missing anything in the narjillo's state. diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/creature/EggTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/creature/EggTest.java index 1a6aa886..ac1b17b3 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/creature/EggTest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/creature/EggTest.java @@ -12,7 +12,7 @@ public class EggTest { - DNA dna = new DNA("{1_2_3}"); + DNA dna = new DNA(1, "{1_2_3}"); Egg egg = new Egg(dna, Vector.cartesian(10, 20), 100, 20); @Test diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/creature/NarjilloEnergyLossTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/creature/NarjilloEnergyLossTest.java index 4485ab17..e95d9c9f 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/creature/NarjilloEnergyLossTest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/creature/NarjilloEnergyLossTest.java @@ -18,9 +18,9 @@ public class NarjilloEnergyLossTest { @Before public void initializeNarjillos() { - smallerNarjillo = new Narjillo(new DNA("{0_255_255_255_255_255_255_255}{0_255_255_255_255_255_255_255}"), new Body(new Head(10, 10, new ColorByte(10), 1, 0.5)), Vector.ZERO, 10000); + smallerNarjillo = new Narjillo(new DNA(1, "{0_255_255_255_255_255_255_255}{0_255_255_255_255_255_255_255}"), new Body(new Head(10, 10, new ColorByte(10), 1, 0.5)), Vector.ZERO, 10000); - DNA dna = new DNA("{0_255_255_255_255_255_255_255}{0_255_255_255_255_255_255_255}{0_255_255_255_255_255_255_255}{0_255_255_255_255_255_255_255}{0_255_255_255_255_255_255_255}"); + DNA dna = new DNA(2, "{0_255_255_255_255_255_255_255}{0_255_255_255_255_255_255_255}{0_255_255_255_255_255_255_255}{0_255_255_255_255_255_255_255}{0_255_255_255_255_255_255_255}"); biggerNarjillo = new Narjillo(dna, new Embryo(dna).develop(), Vector.ZERO, 10000); } @@ -34,7 +34,7 @@ public void itLosesEnergyFasterWhileMovingIfItIsBigger() { @Test public void itsEnergyNaturallyDecreasesWithOldAgeEvenWhenItDoesntMove() { - DNA dna = new DNA("{1_1_1_1_1_1_1_1"); + DNA dna = new DNA(1, "{1_1_1_1_1_1_1_1"); Narjillo narjilloThatCannotMove = new Narjillo(dna, new Embryo(dna).develop(), Vector.ZERO, 10000); for (int i = 0; i < Narjillo.MAX_LIFESPAN + 1; i++) diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/ecosystem/EcosystemTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/ecosystem/EcosystemTest.java index 1a0cae52..5130b4f1 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/ecosystem/EcosystemTest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/ecosystem/EcosystemTest.java @@ -38,7 +38,7 @@ public void initialize() { } private Narjillo insertNarjillo(Vector position) { - DNA dna = DNA.random(ranGen); + DNA dna = DNA.random(1, ranGen); Narjillo result = new Narjillo(dna, new Embryo(dna).develop(), position, 10000); ecosystem.insertNarjillo(result); return result; diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNAAnalysisTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNAAnalysisTest.java index a827f9c9..85a10587 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNAAnalysisTest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNAAnalysisTest.java @@ -8,9 +8,9 @@ public class DNAAnalysisTest { @Test public void computesTheDistanceBetweenDNAStrands() { - DNA dna1 = new DNA("001_001_001"); - DNA dna2 = new DNA("001_002_001"); - DNA dna3 = new DNA("001_002_002"); + DNA dna1 = new DNA(1, "001_001_001"); + DNA dna2 = new DNA(2, "001_002_001"); + DNA dna3 = new DNA(3, "001_002_002"); assertEquals(0, dna1.getLevenshteinDistanceFrom(dna1)); assertEquals(1, dna1.getLevenshteinDistanceFrom(dna2)); @@ -19,7 +19,7 @@ public void computesTheDistanceBetweenDNAStrands() { assertEquals(dna3.getLevenshteinDistanceFrom(dna1), dna1.getLevenshteinDistanceFrom(dna3)); - DNA dna4 = new DNA("001_002"); + DNA dna4 = new DNA(4, "001_002"); assertEquals(2, dna1.getLevenshteinDistanceFrom(dna4)); assertEquals(2, dna4.getLevenshteinDistanceFrom(dna1)); diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNADocumentTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNADocumentTest.java index 2d669ae7..a4cd9a81 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNADocumentTest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNADocumentTest.java @@ -70,7 +70,7 @@ public void ignoresAnythingAfterTheGenesLine() { @Test public void convertsDNAToADocumentString() { - DNA dna = new DNA("1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_255"); + DNA dna = new DNA(1, "1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_255"); assertEquals("{001_002_003_004_005_006_007_008_009}{010_011_012_013_014_015_016_017_018}{255_000_000_000_000_000_000_000_000}", dna.toString()); } diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNAIteratorTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNAIteratorTest.java index deef7616..a52a724e 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNAIteratorTest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNAIteratorTest.java @@ -11,7 +11,7 @@ public class DNAIteratorTest { public void iteratesOverChromosomes() { String genes = "{1_2_3_4_5_6_7_8_9}{10_11_12_13_14_15_16_17_18}"; - DNA dna = new DNA(genes); + DNA dna = new DNA(1, genes); DNAIterator iterator = new DNAIterator(dna); assertEquals(new Chromosome(1, 2, 3, 4, 5, 6, 7, 8, 9), iterator.nextChromosome()); @@ -23,7 +23,7 @@ public void iteratesOverChromosomes() { public void padsUnterminatedLastChromosome() { String genes = "{1_2_3_4_5_6_7_8_9}{10_11}"; - DNA dna = new DNA(genes); + DNA dna = new DNA(1, genes); DNAIterator iterator = new DNAIterator(dna); assertEquals(new Chromosome(1, 2, 3, 4, 5, 6, 7, 8, 9), iterator.nextChromosome()); @@ -35,7 +35,7 @@ public void padsUnterminatedLastChromosome() { public void padsUnterminatedSingleChromosome() { String genes = "{1_2_3}"; - DNA dna = new DNA(genes); + DNA dna = new DNA(1, genes); DNAIterator iterator = new DNAIterator(dna); assertEquals(new Chromosome(new int[]{1, 2, 3, 0, 0, 0, 0}), iterator.nextChromosome()); @@ -43,7 +43,7 @@ public void padsUnterminatedSingleChromosome() { } public void alwaysReturnsAtLeastOneChromosome() { - DNA dna = new DNA("{}"); + DNA dna = new DNA(1, "{}"); DNAIterator iterator = new DNAIterator(dna); assertEquals(new Chromosome(new int[]{0, 0, 0, 0, 0, 0, 0}), iterator.nextChromosome()); diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNAObserverTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNAObserverTest.java deleted file mode 100644 index a6bd5706..00000000 --- a/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNAObserverTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.nusco.narjillos.genomics; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.nusco.narjillos.shared.utilities.RanGen; - -public class DNAObserverTest { - - final String[] log = new String[1]; - - @Before - public void setUpObserver() { - DNA.setObserver(new DNAObserver() { - - @Override - public void created(DNA newDNA, DNA parent) { - log[0] = newDNA + "," + parent; - } - - @Override - public void removed(DNA dna) { - log[0] = "Removed: " + dna; - } - }); - } - - @After - public void tearDownObserver() { - DNA.setObserver(DNAObserver.NULL); - } - - @Test - public void observesCreationgOfNewDNA() { - DNA parentDna = new DNA("{1}"); - - String expected = parentDna.toString() + ",null"; - assertEquals(expected, log[0]); - } - - @Test - public void observesDNACopy() { - DNA parentDna = new DNA("{1}"); - DNA childDNA = parentDna.copyWithMutations(new RanGen(1234)); - - String expected = childDNA.toString() + "," + parentDna.toString(); - assertEquals(expected, log[0]); - } - - @Test - public void observesDNARemoval() { - DNA dna = new DNA("{1}"); - dna.destroy(); - - String expected = "Removed: " + dna.toString(); - assertEquals(expected, log[0]); - } -} diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNATest.java b/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNATest.java index a2c9ffad..4bad4276 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNATest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/genomics/DNATest.java @@ -10,31 +10,23 @@ public class DNATest { @Test public void hasASerialId() { - DNA dna1 = new DNA("{1_2_3}"); - DNA dna2 = new DNA("{1_2_3}"); + DNA dna = new DNA(42, "{1_2_3}"); - assertEquals(dna2.getId(), dna1.getId() + 1); + assertEquals(dna.getId(), 42); } @Test public void hasAnArrayOfGenes() { - DNA dna = new DNA("{1_2_255}"); + DNA dna = new DNA(1, "{1_2_255}"); assertArrayEquals(new Integer[] {1, 2, 255}, dna.getGenes()); } @Test public void isOnlyEqualIfItHasTheSameId() { - DNA dna1 = new DNA("{1_2_3}"); - DNA dna2 = new DNA("{1_2_3}"); - - final long dna1Id = dna1.getId(); - DNA dna3 = new DNA("{4_5_6}") { - @Override - public long getId() { - return dna1Id; - } - }; + DNA dna1 = new DNA(1, "{1_2_3}"); + DNA dna2 = new DNA(2, "{1_2_3}"); + DNA dna3 = new DNA(1, "{4_5_6}"); assertFalse(dna1.equals(dna2)); assertEquals(dna3, dna1); @@ -42,28 +34,28 @@ public long getId() { @Test public void convertsToADNADocumentString() { - DNA dna = new DNA("1_2_3"); + DNA dna = new DNA(1, "1_2_3"); assertEquals("{001_002_003_000_000_000_000_000_000}", dna.toString()); } @Test public void isNeverEmpty() { - DNA dna = new DNA("{}"); + DNA dna = new DNA(1, "{}"); assertEquals("{000_000_000_000_000_000_000_000_000}", dna.toString()); } @Test public void clipsGenesToByteSizeWhenCreatedWithAnArray() { - DNA dna = new DNA("1_-1_256"); + DNA dna = new DNA(1, "1_-1_256"); assertArrayEquals(new Integer[] {1, 0, 255}, dna.getGenes()); } @Test public void clipsGenesToByteSizeWhenCreatedWithAString() { - DNA dna = new DNA("1_0_256"); + DNA dna = new DNA(1, "1_0_256"); assertArrayEquals(new Integer[] {1, 0, 255}, dna.getGenes()); } @@ -72,7 +64,7 @@ public void clipsGenesToByteSizeWhenCreatedWithAString() { public void createsDNAFromADNADocumentString() { String dnaString = "comment\n" + "1_022_255"; - DNA dna = new DNA(dnaString); + DNA dna = new DNA(1, dnaString); assertArrayEquals(new Integer[] {1, 22, 255}, dna.getGenes()); } diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/genomics/GenePoolTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/genomics/GenePoolTest.java index ca8e2759..5be91bb8 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/genomics/GenePoolTest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/genomics/GenePoolTest.java @@ -5,7 +5,6 @@ import java.util.List; -import org.junit.After; import org.junit.Before; import org.junit.Test; import org.nusco.narjillos.shared.utilities.RanGen; @@ -16,36 +15,29 @@ public class GenePoolTest { GenePool genePool = new GenePool(); @Before - public void setUpObserver() { - DNA.setObserver(genePool); + public void setUpGenePool() { genePool.enableTracking(); } - @After - public void tearDownObserver() { - DNA.setObserver(DNAObserver.NULL); - } - @Test public void doesNotTrackByDefault() { GenePool disabledGenePool = new GenePool(); - DNA.setObserver(disabledGenePool); - - new DNA("{0}"); + + disabledGenePool.createDNA("{0}"); assertEquals(0, disabledGenePool.getCurrentPoolSize()); } @Test public void tracksAncestry() { - DNA parent1 = new DNA("{0}"); - parent1.copyWithMutations(ranGen); + DNA parent1 = genePool.createDNA("{0}"); + genePool.mutateDNA(parent1, ranGen); - DNA parent2 = new DNA("{0}"); - DNA child2_1 = parent2.copyWithMutations(ranGen); - parent2.copyWithMutations(ranGen); + DNA parent2 = genePool.createDNA("{0}"); + DNA child2_1 = genePool.mutateDNA(parent2, ranGen); + genePool.mutateDNA(parent2, ranGen); - DNA child2_2_1 = child2_1.copyWithMutations(ranGen); + DNA child2_2_1 = genePool.mutateDNA(child2_1, ranGen); List ancestry = genePool.getAncestry(child2_2_1); @@ -57,11 +49,11 @@ public void tracksAncestry() { @Test public void getsMostSuccessfulDNA() { - new DNA("111_111_111_222_111_000_000_000_000"); - new DNA("111_111_111_111_111_000_000_000_000"); - new DNA("111_111_111_222_222_000_000_000_000"); - new DNA("111_111_222_111_222_000_000_000_000"); - new DNA("111_222_222_222_222_000_000_000_000"); + genePool.createDNA("111_111_111_222_111_000_000_000_000"); + genePool.createDNA("111_111_111_111_111_000_000_000_000"); + genePool.createDNA("111_111_111_222_222_000_000_000_000"); + genePool.createDNA("111_111_222_111_222_000_000_000_000"); + genePool.createDNA("111_222_222_222_222_000_000_000_000"); DNA mostSuccessful = genePool.getMostSuccessfulDNA(); @@ -75,13 +67,13 @@ public void getsNullAsTheMostSuccesfulInAnEmptyPool() { @Test public void canRemoveDNA() { - new DNA("111_111_111_222_111_000_000_000_000"); - DNA thisOneWillDie = new DNA("111_111_111_111_111_000_000_000_000"); - new DNA("111_111_111_222_222_000_000_000_000"); - new DNA("111_111_222_111_222_000_000_000_000"); - new DNA("111_222_222_222_222_000_000_000_000"); + genePool.createDNA("111_111_111_222_111_000_000_000_000"); + DNA thisOneWillDie = genePool.createDNA("111_111_111_111_111_000_000_000_000"); + genePool.createDNA("111_111_111_222_222_000_000_000_000"); + genePool.createDNA("111_111_222_111_222_000_000_000_000"); + genePool.createDNA("111_222_222_222_222_000_000_000_000"); - thisOneWillDie.destroy(); + genePool.remove(thisOneWillDie); DNA mostSuccessful = genePool.getMostSuccessfulDNA(); assertEquals("{111_111_111_222_111_000_000_000_000}", mostSuccessful.toString()); @@ -89,11 +81,10 @@ public void canRemoveDNA() { @Test public void neverRemovesDNAFromHistory() { - RanGen ranGen = new RanGen(42); for (int i = 0; i < 100; i++) { - DNA dna = DNA.random(ranGen); + DNA dna = genePool.createRandomDNA(ranGen); if (i >= 50) - dna.destroy(); + genePool.remove(dna); } assertEquals(50, genePool.getCurrentPoolSize()); diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONDNASerializationTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONDNASerializationTest.java index 3aeec629..4c7d7103 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONDNASerializationTest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONDNASerializationTest.java @@ -11,7 +11,7 @@ public class JSONDNASerializationTest { @Test public void serializesAndDeserializesDNA() { - DNA dna = new DNA("{001_002_003_004_005_006_007_008_009}{010_011_012_013_014_15_16_17_18}"); + DNA dna = new DNA(1, "{001_002_003_004_005_006_007_008_009}{010_011_012_013_014_15_16_17_18}"); String json = JSON.toJson(dna, DNA.class); DNA deserialized = JSON.fromJson(json, DNA.class); diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONEcosystemSerializationTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONEcosystemSerializationTest.java index 889d4735..d6e2ee38 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONEcosystemSerializationTest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONEcosystemSerializationTest.java @@ -22,9 +22,9 @@ public void serializesAndDeserializesEcosystem() { Ecosystem ecosystem = new Ecosystem(123); FoodPiece food1 = ecosystem.spawnFood(Vector.cartesian(10, 10)); FoodPiece food2 = ecosystem.spawnFood(Vector.cartesian(20, 20)); - Egg egg = ecosystem.spawnEgg(new DNA("{1_2_3_4_5_6_7_8}"), Vector.cartesian(30, 30), new RanGen(0)); + Egg egg = ecosystem.spawnEgg(new DNA(1, "{1_2_3_4_5_6_7_8}"), Vector.cartesian(30, 30), new RanGen(0)); - DNA dna = DNA.random(new RanGen(100)); + DNA dna = DNA.random(1, new RanGen(100)); Narjillo narjillo = new Narjillo(dna, new Embryo(dna).develop(), Vector.cartesian(100, 101), 10000); ecosystem.insertNarjillo(narjillo); diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONGenePoolSerializationTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONGenePoolSerializationTest.java index 672f14fe..ee552307 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONGenePoolSerializationTest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONGenePoolSerializationTest.java @@ -4,41 +4,30 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import org.junit.After; import org.junit.Test; import org.nusco.narjillos.genomics.DNA; -import org.nusco.narjillos.genomics.DNAObserver; import org.nusco.narjillos.genomics.GenePool; import org.nusco.narjillos.shared.utilities.RanGen; public class JSONGenePoolSerializationTest { GenePool genePool = new GenePool(); - - @After - public void tearDownDNAObserver() { - DNA.setObserver(DNAObserver.NULL); - } @Test public void serializesAndDeserializesGenePools() { RanGen ranGen = new RanGen(1234); - DNA.setObserver(genePool); genePool.enableTracking(); - DNA parent = DNA.random(ranGen); - DNA child1 = parent.copyWithMutations(ranGen); - DNA child2 = parent.copyWithMutations(ranGen); - parent.copyWithMutations(ranGen); + DNA parent = genePool.createRandomDNA(ranGen); + DNA child1 = genePool.mutateDNA(parent, ranGen); + DNA child2 = genePool.mutateDNA(parent, ranGen); + genePool.mutateDNA(parent, ranGen); + genePool.remove(child2); - child2.destroy(); - - child1.copyWithMutations(ranGen); - DNA child3 = child1.copyWithMutations(ranGen); + genePool.mutateDNA(child1, ranGen); + DNA child3 = genePool.mutateDNA(child1, ranGen); - DNA.setObserver(DNAObserver.NULL); - String json = JSON.toJson(genePool, GenePool.class); GenePool deserialized = JSON.fromJson(json, GenePool.class); diff --git a/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONThingSerializationTest.java b/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONThingSerializationTest.java index 28428a84..2ee26d50 100644 --- a/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONThingSerializationTest.java +++ b/narjillos-core/src/test/java/org/nusco/narjillos/serializer/JSONThingSerializationTest.java @@ -28,7 +28,7 @@ public void serializesAndDeserializesFoodPieces() { @Test public void serializesAndDeserializesEggs() { - DNA dna = new DNA("{1_2}"); + DNA dna = new DNA(1, "{1_2}"); Egg egg = new Egg(dna, Vector.cartesian(10, 20), 101, 10); String json = JSON.toJson(egg, Thing.class); @@ -42,7 +42,7 @@ public void serializesAndDeserializesEggs() { @Test public void serializesAndDeserializesNarjillos() { String genes = "{001_002_003_004_005_006_007_008_009}{001_002_003_004_005_006_007_008_009}{001_002_003_004_005_006_007_008_009}{001_002_003_004_005_006_007_008_009}{001_002_003_004_005_006_007_008_009}"; - DNA dna = new DNA(genes); + DNA dna = new DNA(1, genes); Narjillo narjillo = new Narjillo(dna, new Embryo(dna).develop(), Vector.cartesian(10, 20), 10000); narjillo.setTarget(Vector.cartesian(100, 200)); for (int i = 0; i < 10; i++) diff --git a/narjillos-petridish/src/test/java/org/nusco/narjillos/utilities/LocatorTest.java b/narjillos-petridish/src/test/java/org/nusco/narjillos/utilities/LocatorTest.java index ce6e1387..515c684c 100644 --- a/narjillos-petridish/src/test/java/org/nusco/narjillos/utilities/LocatorTest.java +++ b/narjillos-petridish/src/test/java/org/nusco/narjillos/utilities/LocatorTest.java @@ -25,7 +25,7 @@ public void initialize() { } private Narjillo insertNarjillo(Vector position) { - DNA dna = new DNA("{145_227_116_072_163_201_077_221_217}{060_227_157_252_209_149_056_114_167}{250_253_092_189_010_247_016_214_009}{027_039_203_179_042_042_175_110_008}"); + DNA dna = new DNA(1, "{145_227_116_072_163_201_077_221_217}{060_227_157_252_209_149_056_114_167}{250_253_092_189_010_247_016_214_009}{027_039_203_179_042_042_175_110_008}"); Narjillo result = new Narjillo(dna, new Embryo(dna).develop(), position, 10000); ecosystem.insertNarjillo(result); return result;