package edu.wright.hendrix11.conway.logic;

import java.util.HashSet;
import java.util.Set;

/**
 * @author Joe Hendrix
 */
public class Grid {

    private Set<Cell> aliveCells = new HashSet<>();
    private int generation = 0;

    private boolean classInv() {
        boolean invariant = true;

        for (Cell cell : aliveCells) {
            if (!cell.isAlive()) {
                invariant = false;
            }
        }

        return invariant;
    }

    public void addLivingCell(Cell cell) {
        assert cell.isAlive();
        aliveCells.add(cell);
        assert classInv();
    }

    public void clear() {
        // The copy prevents a java.util.ConcurrentModificationException
        Set<Cell> copy = new HashSet<>(aliveCells);
        copy.forEach(Cell::toggle);
        assert aliveCells.isEmpty();
        assert classInv();
    }

    public int getGeneration() {
        return generation;
    }

    public void removeDeadCell(Cell cell) {
        assert !cell.isAlive();
        aliveCells.remove(cell);
        assert !aliveCells.contains(cell);
        assert classInv();
    }

    public void tick() {
        assert classInv();
        Set<Cell> toggleTheseCells = new HashSet<>();

        checkLivingCells(toggleTheseCells);
        checkAdjacentDeadCells(toggleTheseCells);

        toggleCells(toggleTheseCells);

        generation++;

        assert classInv();
    }

    private void checkAdjacentDeadCells(Set<Cell> toggleTheseCells) {
        aliveCells.forEach(cell -> cell.getNeighbors().forEach(neighbor -> {
            if (!neighbor.isAlive() && checkDeadCell(neighbor)) {
                    toggleTheseCells.add(neighbor);
            }
        }));
    }

    private boolean checkDeadCell(Cell deadCell) {
        assert !deadCell.isAlive();

        int numberOfLivingNeighbors = deadCell.getNumberLivingNeighbors();

        assert numberOfLivingNeighbors >= 0 && numberOfLivingNeighbors <= 8;

        return numberOfLivingNeighbors == 3;
    }

    private boolean checkLivingCell(Cell livingCell) {
        assert livingCell.isAlive();

        int numberOfLivingNeighbors = livingCell.getNumberLivingNeighbors();

        assert numberOfLivingNeighbors >= 0 && numberOfLivingNeighbors <= 8;

        return numberOfLivingNeighbors < 2 || numberOfLivingNeighbors > 3;
    }

    private void checkLivingCells(Set<Cell> toggleTheseCells) {
        aliveCells.forEach(cell ->  {
            if (checkLivingCell(cell)) {
                toggleTheseCells.add(cell);
            }
        });
    }

    private void toggleCells(Set<Cell> toggleTheseCells) {
        toggleTheseCells.forEach(Cell::toggle);
    }
}

@@ -223,16 +223,132 @@
 n = 0;%0A%0A
+    /**%0A     * All cells in aliveCells must be alive.%0A     * The current generation can never be negative.%0A     */ %0A
     priv
@@ -544,52 +544,378 @@
   %7D%0A
-%0A        return invariant;%0A    %7D%0A%0A    public
+        %0A        if(generation %3C 0) %7B%0A            invariant = false;%0A        %7D%0A%0A        return invariant;%0A    %7D%0A%0A    /**%0A     * Adds a living cell to the aliveCells set. This method is package-private and is called explicity by%0A     * the %7B@link Cell%7D class.%0A     * %0A     * precondition:    cell is alive%0A     * postcondition:   cell is in aliveCells%0A     * %0A     */%0A   
  voi
@@ -966,32 +966,41 @@
 cell.isAlive();%0A
+        %0A
         aliveCel
@@ -1025,33 +1025,390 @@
     
-assert classInv();%0A    %7D%0A
+%0A        assert aliveCells.contains(cell);%0A        assert classInv();%0A    %7D%0A%0A    /**%0A     * Empties the aliveCells set by toggling each living cell. The now-dead cell will remove itself%0A     * from the aliveCell set.%0A     * %0A     * precondition:    aliveCells is not null%0A     * postcondition:   aliveCells is empty and all cells that were in aliveCells are not alive%0A     *%0A     */
 %0A   
@@ -1654,32 +1654,87 @@
 ssInv();%0A    %7D%0A%0A
+    /**%0A     * Returns the current generation.%0A     */%0A
     public int g
@@ -1784,30 +1784,288 @@
 %0A    %7D%0A%0A    
-public
+/**%0A     * Removes a dead cell from the aliveCells set. This method is package-private and is called explicity by%0A     * the %7B@link Cell%7D class.%0A     * %0A     * precondition:    cell is not alive%0A     * postcondition:   cell is not in aliveCells%0A     * %0A     */%0A   
  void remove
@@ -2110,32 +2110,41 @@
 cell.isAlive();%0A
+        %0A
         aliveCel
@@ -2152,32 +2152,41 @@
 s.remove(cell);%0A
+        %0A
         assert !
@@ -2294,24 +2294,33 @@
 classInv();%0A
+        %0A
         Set%3C
@@ -2845,32 +2845,114 @@
     %7D));%0A    %7D%0A%0A
+    /**%0A     * %0A     * precondition:    %0A     * postcondition:   %0A     * %0A     */%0A
     private bool
@@ -3221,32 +3221,114 @@
 rs == 3;%0A    %7D%0A%0A
+    /**%0A     * %0A     * precondition:    %0A     * postcondition:   %0A     * %0A     */%0A
     private bool
@@ -3634,32 +3634,114 @@
 ors %3E 3;%0A    %7D%0A%0A
+    /**%0A     * %0A     * precondition:    %0A     * postcondition:   %0A     * %0A     */%0A
     private void

Update Grid.java