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>> modifiedCells = new HashSet<ICell<StateType>>();
		for (ICell<StateType> cell : cellsToCalculate) {
			if (cell.isNextStateDifferent()) {
				cell.applyNextState();
				modifiedCells.add(cell);
			}
		}

		// check the next cells to calculate
		cellsToCalculate.clear();
		for (ICell<StateType> cell : modifiedCells) {
			cellsToCalculate.addAll(getCellsDependingTo(cell));
		}
	}

	/**
	 * 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. When this
	 * method is called, <b>all the cells</b> have their new state (the step is
	 * finished).<br/>
	 * <br/>
	 * The default implementation return all the cells of the space. This method
	 * may 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 getSpace().getAllCells();
	}

	/**
	 * 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;
	}

}

@@ -1071,16 +1071,129 @@
 e%3E%3E();%0A%0A
+%09/**%0A%09 * Activate/deactivate the dependency optimization.%0A%09 */%0A%09private boolean isDependencyConsidered = false;%0A%0A
 %09/**%0A%09 *
@@ -1243,16 +1243,16 @@
  cells.%0A
-
 %09 * %0A%09 *
@@ -2127,16 +2127,51 @@
 %09%7D%0A%09%09%7D%0A%0A
+%09%09if (isDependencyConsidered()) %7B%0A%09
 %09%09// che
@@ -2201,16 +2201,17 @@
 lculate%0A
+%09
 %09%09cellsT
@@ -2228,24 +2228,25 @@
 .clear();%0A%09%09
+%09
 for (ICell%3CS
@@ -2275,24 +2275,25 @@
 iedCells) %7B%0A
+%09
 %09%09%09cellsToCa
@@ -2335,16 +2335,21 @@
 cell));%0A
+%09%09%09%7D%0A
 %09%09%7D%0A%09%7D%0A%0A
@@ -3566,24 +3566,24 @@
 lculate() %7B%0A
-
 %09%09return cel
@@ -3601,10 +3601,715 @@
 te;%0A%09%7D%0A%0A
+%09/**%0A%09 * @param isDependencyConsidered%0A%09 */%0A%09public void setDependencyConsidered(boolean isDependencyConsidered) %7B%0A%09%09this.isDependencyConsidered = isDependencyConsidered;%0A%09%7D%0A%0A%09/**%0A%09 * Tell if the dependencies are considered. These dependencies allow to%0A%09 * reduce the next cells to be calculated. This optimization can be quite%0A%09 * efficient for spaces where only a small amount of cells (compared to the%0A%09 * total) is calculated on each step. For a space where all the cells are%0A%09 * always calculated, it is strongly recommended to deactivate it.%0A%09 * %0A%09 * @return true of the optimization is activated, false otherwise%0A%09 */%0A%09public boolean isDependencyConsidered() %7B%0A%09%09return isDependencyConsidered;%0A%09%7D%0A%0A
 %7D%0A

Add the possibility to activate/deactivate the dependency check.