package kata.gameoflife.a20170806; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import org.junit.Test; /** * Game of Life Kata. * Copyright (c) 2017, Peter Kofler, licensed under BSD License. */ public class TransitGenerationTest { LookupLivingCells lookupLivingCells = new LookupLivingCells(); public static class TransitGeneration { private final LookupLivingCells currentLivingCells; private final LookupLivingCells nextLivingCells = new LookupLivingCells(); public TransitGeneration(LookupLivingCells currentGeneration) { this.currentLivingCells = currentGeneration; } public LookupLivingCells transit() { for (int x = 0; x < 10; x++) { for (int y = 0; y < 10; y++) { LocateCell locateCell = new LocateCell(x, y); transit(locateCell); } } return nextLivingCells; } private void transit(LocateCell locateCell) { int livingNeigbours = numberOfAliveNeigbourCells(locateCell); boolean isAlive = currentLivingCells.isAlive(locateCell); Classify classify = getClassify(isAlive, livingNeigbours); if (classify.asOptimal()) { nextLivingCells.reproduce(locateCell); } } private int numberOfAliveNeigbourCells(LocateCell locateCell) { return new CountLivingNeighbourCells( new LocateNeighbourCells( locateCell), currentLivingCells).count(); } private static Classify getClassify(boolean isAlive, int numberOfAliveNeigbours) { Classify classify; if (isAlive) { classify = ClassifyPopulation.havingNeighbours(numberOfAliveNeigbours); } else { classify = ClassifyReproduction.havingNeighbours(numberOfAliveNeigbours); } return classify; } @Deprecated // only used by old tests public Object transit(Classify classify) { return classify.asOptimal() ? ALIVE : DEAD; } } static final Object DEAD = new Object(); static final Object ALIVE = new Object(); // I assume this was our first test. @Test public void liveCellWithOneNeighbourShouldDie() { assertDead(new TransitGeneration(lookupLivingCells).transit(ClassifyPopulation.havingNeighbours(1))); } @Test public void liveCellWithZeroNeighbourShouldDie() { assertDead(new TransitGeneration(lookupLivingCells).transit(ClassifyPopulation.havingNeighbours(0))); } @Test public void liveCellWithTwoNeighbourShouldLiveOn() { assertAlive(new TransitGeneration(lookupLivingCells).transit(ClassifyPopulation.havingNeighbours(2))); } @Test public void liveCellWithFourNeighbourShouldDie() { assertDead(new TransitGeneration(lookupLivingCells).transit(ClassifyPopulation.havingNeighbours(4))); } @Test public void deadCellWithThreeLiveNeighboursShouldBeBorn() { assertAlive(new TransitGeneration(lookupLivingCells).transit(ClassifyReproduction.havingNeighbours(3))); } @Test public void deadCellWithTwoLiveNeighboursShouldStayDead() { assertDead(new TransitGeneration(lookupLivingCells).transit(ClassifyReproduction.havingNeighbours(2))); } private void assertAlive(Object transit) { assertSame(ALIVE, transit); } private void assertDead(Object transit) { assertSame(DEAD, transit); } // The business rules are in place. What comes next? // Where does the number of life neighbours come from? @Test public void lonelyCellHasNoNeighbours() { assertEquals(0, new CountLivingNeighbourCells( new LocateNeighbourCells( new LocateCell(1, 1)), lookupLivingCells).count()); } @Test public void hasOneNeighbourInLowerLeft() { givenCellAt(new LocateCell(0, 0)); assertEquals(1, new CountLivingNeighbourCells( new LocateNeighbourCells( new LocateCell(1, 1)), lookupLivingCells).count()); } @Test public void hasAllNeighbours() { givenCellAt(new LocateCell(0, 0)); givenCellAt(new LocateCell(0, 1)); givenCellAt(new LocateCell(0, 2)); givenCellAt(new LocateCell(1, 2)); givenCellAt(new LocateCell(2, 2)); givenCellAt(new LocateCell(2, 1)); givenCellAt(new LocateCell(2, 0)); givenCellAt(new LocateCell(1, 0)); assertEquals(8, new CountLivingNeighbourCells( new LocateNeighbourCells( new LocateCell(1, 1)), lookupLivingCells).count()); } private void givenCellAt(LocateCell locateCell) { lookupLivingCells.reproduce(locateCell); } @Test public void blinkerBlinks() { givenCellAt(new LocateCell(1, 0)); givenCellAt(new LocateCell(1, 1)); givenCellAt(new LocateCell(1, 2)); LookupLivingCells newCells = new TransitGeneration(lookupLivingCells).transit(); LookupLivingCells expectedCells = new LookupLivingCells(); expectedCells.reproduce(new LocateCell(0, 1)); expectedCells.reproduce(new LocateCell(1, 1)); expectedCells.reproduce(new LocateCell(2, 1)); assertEquals(expectedCells, newCells); // bad, checking on internal values. // TODO later what is the outside view of cells } }