package org.cellularautomaton;

import java.util.Collection;
import java.util.HashSet;

import org.cellularautomaton.cell.ICell;
import org.cellularautomaton.space.ISpace;

/**
 * A cellular automaton is a space of evolving cells. Each cell evolves
 * considering its actual state and the states of other cells.
 * 
 * @author Matthieu Vergne (matthieu.vergne@gmail.com)
 * 
 * @param <StateType>
 *            the type of data used by each cell, it can be {@link Boolean} for
 *            a simple "On/Off" state, a numeral state like {@link Integer} or
 *            {@link Float} for arithmetical states, or any specific type of
 *            data for particular uses (just consider all the cells use the same
 *            type).
 */
public class CellularAutomaton<StateType> {

	/**
	 * The space of cells this automaton work on.
	 */
	private final ISpace<StateType> cellSpace;

	/**
	 * The cells which need to see their new state calculated during the next
	 * step.
	 */
	private final Collection<ICell<StateType>> cellsToCalculate = new HashSet<ICell<StateType>>();

	/**
	 * Create an automaton on a specific space of cells.
	 * 
	 * @param cellSpace
	 *            the space of cells to work on
	 */
	public CellularAutomaton(ISpace<StateType> cellSpace) {
		this.cellSpace = cellSpace;
		cellsToCalculate.addAll(cellSpace.getAllCells());
	}

	/**
	 * Calculate the next state of each cell. After this step, the logical way
	 * is to apply it with {@link #applyNextStep()}.
	 */
	public void calculateNextStep() {
		for (ICell<StateType> cell : cellsToCalculate) {
			cell.calculateNextState();
		}
	}

	/**
	 * Apply the previously calculated states of each cell. If some cells have
	 * not calculated yet, their state does not change.
	 */
	public void applyNextStep() {
		Collection<ICell<StateType>> nextCellsToCalculate = new HashSet<ICell<StateType>>();
		for (ICell<StateType> cell : cellsToCalculate) {
			if (cell.isNextStateDifferent()) {
				cell.applyNextState();
				nextCellsToCalculate.addAll(getCellsDependingTo(cell));
			}
		}

		cellsToCalculate.clear();
		cellsToCalculate.addAll(nextCellsToCalculate);
	}

	/**
	 * This method allows to know the cells which need to be calculated at the
	 * next step. If a cell see its state modified during the current step, this
	 * method is called to know all the cells which depend on it.<br/>
	 * <br/>
	 * The default implementation return all the calculated cells, so each cell
	 * calculated at the beginning will be calculated at the next step (a priori
	 * all the cells). This method can be overridden to optimize the process.
	 * 
	 * @param cell
	 *            the cell to consider the dependencies with
	 * @return the cells which depends of the cell given in argument
	 */
	protected Collection<ICell<StateType>> getCellsDependingTo(
			ICell<StateType> cell) {
		return getCellsToCalculate();
	}

	/**
	 * Execute a complete step of the automaton. After that, each cell has its
	 * next state.
	 */
	public void doStep() {
		calculateNextStep();
		applyNextStep();
	}

	/**
	 * 
	 * @return the space of cells this automaton work on
	 */
	public ISpace<StateType> getSpace() {
		return cellSpace;
	}

	/**
	 * 
	 * @return the cells which need to see their new state calculated during the
	 *         next step
	 */
	public Collection<ICell<StateType>> getCellsToCalculate() {
		return cellsToCalculate;
	}

}

@@ -1810,36 +1810,29 @@
 eType%3E%3E 
-nextCellsToCalculate
+modifiedCells
  = new H
@@ -1983,62 +1983,31 @@
 %09%09%09%09
-nextCellsToCalculate.addAll(getCellsDependingTo
+modifiedCells.add
 (cell)
-)
 ;%0A%09%09
@@ -2020,34 +2020,122 @@
 %0A%0A%09%09
-cellsToCalculate.clear();%0A
+// check the next cells to calculate%0A%09%09cellsToCalculate.clear();%0A%09%09for (ICell%3CStateType%3E cell : modifiedCells) %7B%0A%09
 %09%09ce
@@ -2160,30 +2160,39 @@
 All(
-nex
+ge
 tCells
-ToCalculate);
+DependingTo(cell));%0A%09%09%7D
 %0A%09%7D%0A
@@ -2417,197 +2417,190 @@
  it.
-%3Cbr/%3E%0A%09 * %3Cbr/%3E%0A%09 * The default implementation return all the calculated cells, so each cell%0A%09 * calculated at the beginning will be calculated at the next step (a priori%0A%09 * all the cells)
+ When this%0A%09 * method is called, %3Cb%3Eall the cells%3C/b%3E have their new state (the step is%0A%09 * finished).%3Cbr/%3E%0A%09 * %3Cbr/%3E%0A%09 * The default implementation return all the cells of the space
 . Th
@@ -2608,20 +2608,24 @@
 s method
- can
+%0A%09 * may
  be over
@@ -2907,32 +2907,35 @@
 turn get
-CellsToCalculate
+Space().getAllCells
 ();%0A%09%7D%0A%0A

Move the looking for next cells to be calculated after the application of the next step. It allows to have a coherent state of all the cells when the method getCellsDependingTo() is called (for the cases this method checks the states of the cells).