diff --git a/src/main/java/SimulatorApplication.java b/src/main/java/SimulatorApplication.java
index fb22b7fa214f754ce32107eeab41b537783adde7..0fed297543cac4bfb5ea3722d445cbc71aea4745 100644
--- a/src/main/java/SimulatorApplication.java
+++ b/src/main/java/SimulatorApplication.java
@@ -1,4 +1,5 @@
 import controller.Controller;
+import controller.Simulation;
 import javafx.application.Application;
 import javafx.application.Platform;
 import javafx.fxml.FXMLLoader;
@@ -6,8 +7,9 @@ import javafx.scene.Parent;
 import javafx.scene.Scene;
 import javafx.stage.Stage;
 import model.CellularAutomatonSimulation;
-import model.states.BriansBrainState;
-import model.states.SeedsState;
+import model.automata.BriansBrainAutomaton;
+import model.automata.GameOfLifeAutomaton;
+import model.automata.SeedsAutomaton;
 
 import java.io.IOException;
 import java.net.URL;
@@ -26,10 +28,10 @@ public class SimulatorApplication extends Application {
 
   public static final Random GENERATOR = new Random();
 
-  private static final String APP_NAME = "Game of Life";
+  private static final String APP_NAME = "2D Cellular automata";
   private static final String VIEW_RESOURCE_PATH = "/view/view.fxml";
 
-  private final CellularAutomatonSimulation<SeedsState> gameOfLife;
+  private final Simulation simulation;
   private Stage primaryStage;
   private Parent view;
 
@@ -37,12 +39,10 @@ public class SimulatorApplication extends Application {
    * Creates a new {@code GameOfLifeApplication} instance.
    */
   public SimulatorApplication() {
-    this.gameOfLife =
+    this.simulation =
       new CellularAutomatonSimulation<>(
-              NUMBER_OF_COLUMNS,
-              NUMBER_OF_ROWS,
-              SeedsState.OFF,
-              SeedsState::random
+              new SeedsAutomaton(NUMBER_OF_COLUMNS,NUMBER_OF_ROWS),
+              GENERATOR
       );
   }
 
@@ -68,7 +68,7 @@ public class SimulatorApplication extends Application {
     loader.setLocation(location);
     view = loader.load();
     Controller controller = loader.getController();
-    controller.setSimulation(gameOfLife);
+    controller.setSimulation(simulation);
   }
 
 
diff --git a/src/main/java/controller/Simulation.java b/src/main/java/controller/Simulation.java
index cf784ea9b705261e6c5bfce6289366aea53f427a..674a0fd910b383cc55a0ba0e1245ce5309a45499 100644
--- a/src/main/java/controller/Simulation.java
+++ b/src/main/java/controller/Simulation.java
@@ -3,6 +3,7 @@ package controller;
 import datastruct.Coordinate;
 import javafx.beans.property.ReadOnlyLongProperty;
 import javafx.scene.paint.Color;
+import model.OnChangeListener;
 
 public interface Simulation extends Iterable<Coordinate> {
 
@@ -17,7 +18,7 @@ public interface Simulation extends Iterable<Coordinate> {
 
     Color getColor(Coordinate coordinate);
 
-    void setChangeListener(Coordinate coordinate, Runnable run);
+    void setChangeListener(Coordinate coordinate, Runnable listener);
 
     ReadOnlyLongProperty generationNumberProperty();
 
diff --git a/src/main/java/datastruct/Matrix.java b/src/main/java/datastruct/Matrix.java
index dbe33a03b2dd82a50856d2626baf196b852e3ec6..9290fa6d835f82b5566626e33507713bf2bf1852 100644
--- a/src/main/java/datastruct/Matrix.java
+++ b/src/main/java/datastruct/Matrix.java
@@ -4,9 +4,11 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
-public class Matrix<T> {
+public class Matrix<T> implements Iterable<T> {
 
     private final List<List<T>> matrix;
+
+
     private final int width;
     private final int height;
 
@@ -31,6 +33,13 @@ public class Matrix<T> {
         }
     }
 
+    public int width() {
+        return width;
+    }
+
+    public int height() {
+        return height;
+    }
     public T get(int x, int y) {
         return this.matrix.get(x).get(y);
     }
diff --git a/src/main/java/model/Cell.java b/src/main/java/model/Cell.java
index 26bf67856b8a09a842e04b800699478daeb08089..7da6824291fbca70781a2ca2dadfdaba1b3bfb12 100644
--- a/src/main/java/model/Cell.java
+++ b/src/main/java/model/Cell.java
@@ -1,67 +1,50 @@
 package model;
 
-import javafx.beans.property.Property;
-import javafx.beans.property.SimpleObjectProperty;
-import javafx.scene.paint.Color;
+import datastruct.Lens;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
- * {@link Cell} instances represent the cells of <i>The Game of Life</i>.
+ * {@link Cell} instances represent the cells of the grid in a simulation of cellular automata.
  */
 
-public class Cell<S extends State<S>> {
-    private final Property<S> stateProperty;
-
-    public Cell(S initialState) {
-        this.stateProperty = new SimpleObjectProperty<>(initialState);
-    }
+public class Cell<T> implements Lens<T> {
+    private T content;
+    private final List<OnChangeListener<T>> listeners = new ArrayList<>();
 
-    /**
-     * Determines the color associated with the state in which
-     * this {@link Cell} is.
+    /** Initialize a new cell with a given value.
      *
-     * @return the {@link Color} associated with the state in
-     * which this {@link Cell} is
+     * @param initialContent the value initially stored by the cell.
      */
-
-    public Color getColor() {
-        return this.getState().getColor();
+    public Cell(T initialContent) {
+        this.content = initialContent;
     }
 
-    /**
-     * Sets the state of this {@link Cell}.
-     *
-     * @param state the new state of this {@link Cell}
-     */
-
-    public void setState(S state) {
-        getStateProperty().setValue(state);
+    public void addOnChangeListener(OnChangeListener<T> listener) {
+        this.listeners.add(listener);
     }
 
     /**
-     * Returns the current state of this {@link Cell}.
+     * Sets the content of this {@link Cell}.
      *
-     * @return the current state of this {@link Cell}
-     */
-
-    public S getState(){
-        return getStateProperty().getValue();
-    }
-
-    /**
-     * Change the state of this {@link Cell} to the next possible state.
+     * @param value the new content of this {@link Cell}
      */
-
-    public void toggleState() {
-        setState(getState().next());
+    public void set(T value) {
+        this.content = value;
+        for (OnChangeListener<T> listener : this.listeners) {
+            listener.valueChanged(this.content, value);
+        }
     }
 
     /**
-     * Returns this {@link Cell}'s state property.
+     * Returns the current content of this {@link Cell}.
      *
-     * @return this {@link Cell}'s state property.
+     * @return the current content of this {@link Cell}
      */
-    public Property<S> getStateProperty() {
-        return stateProperty;
+    public T get(){
+        return this.content;
     }
 
+
 }
diff --git a/src/main/java/model/CellGrid.java b/src/main/java/model/CellGrid.java
deleted file mode 100644
index 5df1fb5322c6368e93a15f2d4bac4c32e4b65f10..0000000000000000000000000000000000000000
--- a/src/main/java/model/CellGrid.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package model;
-
-import datastruct.Coordinate;
-import datastruct.Lens;
-import datastruct.Matrix;
-
-import java.util.Iterator;
-import java.util.function.Supplier;
-
-
-/**
- * {@link CellGrid} instances represent the grid in <i>The Game of Life</i>.
- */
-public class CellGrid<S extends State<S>> implements Iterable<Cell<S>> {
-
-    private final int numberOfRows;
-    private final int numberOfColumns;
-    private final Matrix<Cell<S>> cells;
-
-    /**
-     * Creates a new {@code Grid} instance given the number of rows and columns.
-     *
-     * @param numberOfColumns the number of columns
-     * @param numberOfRows    the number of rows
-     * @throws IllegalArgumentException if {@code numberOfRows} or {@code numberOfColumns} are
-     *                                  less than or equal to 0
-     */
-    public CellGrid(int numberOfColumns, int numberOfRows, S defaultState) {
-        this.numberOfRows = numberOfRows;
-        this.numberOfColumns = numberOfColumns;
-        this.cells = new Matrix<>(numberOfColumns, numberOfRows, coord -> new Cell<>(defaultState));
-    }
-
-
-    public boolean contains(Coordinate coordinate) {
-        return (coordinate.x() >= 0)
-                && (coordinate.x() < this.numberOfColumns)
-                && (coordinate.y() > 0)
-                && (coordinate.y() <= this.numberOfRows);
-    }
-
-
-    /**
-     * Returns an iterator over the cells in this {@code Grid}.
-     *
-     * @return an iterator over the cells in this {@code Grid}
-     */
-    @Override
-    public Iterator<Cell<S>> iterator() {
-        return this.cells.iterator();
-    }
-
-    public Iterable<Coordinate> coordinates() {
-        return this.cells.coordinates();
-    }
-
-    public Lens<S> at(Coordinate coord) {
-        return new CellLens<>(this.cellAt(coord));
-    }
-
-
-    public Cell<S> cellAt(Coordinate coord) {
-        return this.cells.at(coord).get();
-    }
-
-    private Coordinate wrap(Coordinate coordinate) {
-        return new Coordinate(
-                 modulo(coordinate.x(), getNumberOfColumns()),
-                 modulo(coordinate.y(), getNumberOfRows())
-                );
-    }
-
-    private static int modulo(int n, int d) {
-        int result = n % d;
-        return n < 0 ? result + d : result;
-    }
-    public Lens<S> atWrapped(Coordinate coord) {
-        return this.at(wrap(coord));
-    }
-
-    public Cell<S> cellAtWrapped(Coordinate coord) {
-        return this.cellAt(wrap(coord));
-    }
-
-    /**
-     * Returns the number of rows in this {@code Grid}.
-     *
-     * @return the number of rows in this {@code Grid}
-     */
-    public int getNumberOfRows() {
-        return numberOfRows;
-    }
-
-    /**
-     * Returns the number of columns in this {@code Grid}.
-     *
-     * @return the number of columns in this {@code Grid}
-     */
-    public int getNumberOfColumns() {
-        return numberOfColumns;
-    }
-
-
-
-
-    private Matrix<S> nextGenerationMatrix() {
-        return new Matrix<>(
-                this.numberOfColumns,
-                this.numberOfRows,
-                new NextGenerationInitializer<>(this)
-        );
-    }
-
-    /**
-     * Transitions all {@link Cell}s in this {@code Grid} to the next generation.
-     *
-     * <p>The following rules are applied:
-     * <ul>
-     * <li>Any live {@link Cell} with fewer than two live neighbours dies, i.e. underpopulation.</li>
-     * <li>Any live {@link Cell} with two or three live neighbours lives on to the next
-     * generation.</li>
-     * <li>Any live {@link Cell} with more than three live neighbours dies, i.e. overpopulation.</li>
-     * <li>Any dead {@link Cell} with exactly three live neighbours becomes a live cell, i.e.
-     * reproduction.</li>
-     * </ul>
-     */
-    // TODO: Écrire une version correcte de cette méthode.
-    public void updateToNextGeneration() {
-        Matrix<S> nextStates = this.nextGenerationMatrix();
-        for (Coordinate coordinate : this.coordinates()) {
-            this.cellAt(coordinate).setState(nextStates.get(coordinate));
-        }
-    }
-
-
-    /**
-     * Sets all {@link Cell}s in this {@code Grid} as dead.
-     */
-    // TODO: Écrire une version correcte de cette méthode.
-    public void clear(S clearState) {
-        for (Cell<S> cell : this) {
-            cell.setState(clearState);
-        }
-    }
-
-
-    /**
-     * Goes through each {@link Cell} in this {@code Grid} and sets it states with a
-     * state obtained from the supplier.
-     *
-     * @param supplier {@link Supplier} instance used to decide a state for each cell {@link Cell}.
-     * @throws NullPointerException if {@code supplier} is {@code null}.
-     */
-    // TODO: Écrire une version correcte de cette méthode.
-    public void fillRandomly(Supplier<S> supplier) {
-        for (Cell<S> cell : this) {
-            cell.setState(supplier.get());
-        }
-    }
-}
diff --git a/src/main/java/model/CellLens.java b/src/main/java/model/CellLens.java
deleted file mode 100644
index f9ab4958ce59046b7ce83fb31d0699e695889872..0000000000000000000000000000000000000000
--- a/src/main/java/model/CellLens.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package model;
-
-import datastruct.Lens;
-
-public class CellLens<S extends State<S>> implements Lens<S> {
-
-    private final Cell<S> cell;
-
-    public CellLens(Cell<S> cell) {
-        this.cell = cell;
-    }
-
-    @Override
-    public S get() {
-        return cell.getState();
-    }
-
-    @Override
-    public void set(S value) {
-        cell.setState(value);
-    }
-}
diff --git a/src/main/java/model/CellularAutomaton.java b/src/main/java/model/CellularAutomaton.java
new file mode 100644
index 0000000000000000000000000000000000000000..92b83c4e296bf10fcefd8d20e627871a2127a95e
--- /dev/null
+++ b/src/main/java/model/CellularAutomaton.java
@@ -0,0 +1,10 @@
+package model;
+
+import java.util.Random;
+
+public interface CellularAutomaton<S extends State<S>> {
+    int numberOfColumns();
+    int numberOfRows();
+    S defaultState();
+    S randomState(Random generator);
+}
diff --git a/src/main/java/model/CellularAutomatonSimulation.java b/src/main/java/model/CellularAutomatonSimulation.java
index 8bd51b3b0b3dd8716d78b5e928b8d00054acfe75..aa7404c84cf17b1d4a7c926035892bb6451b0104 100644
--- a/src/main/java/model/CellularAutomatonSimulation.java
+++ b/src/main/java/model/CellularAutomatonSimulation.java
@@ -2,14 +2,15 @@ package model;
 
 import controller.Simulation;
 import datastruct.Coordinate;
+import datastruct.Matrix;
 import javafx.beans.property.ReadOnlyLongProperty;
 import javafx.beans.property.ReadOnlyLongWrapper;
 import javafx.scene.paint.Color;
-
 import java.util.Iterator;
+import java.util.Random;
 import java.util.function.Supplier;
 
-import static java.util.Objects.requireNonNull;
+
 
 /**
  * {@link CellularAutomatonSimulation} instances run <i>The Game of Life</i>.
@@ -17,69 +18,94 @@ import static java.util.Objects.requireNonNull;
 public class CellularAutomatonSimulation<S extends State<S>>
         implements Simulation {
 
-    private final CellGrid<S> grid;
-    private final Supplier<S> randomState;
-    private final S defaultState;
+    private final Matrix<Cell<S>> grid;
     private final ReadOnlyLongWrapper generationNumber = new ReadOnlyLongWrapper();
+    private final CellularAutomaton<S> automaton;
+    private final Random generator;
 
     /**
-     * Creates a new {@code CellularAutomataSimulation} instance for a given automaton.
+     * Creates a new {@link CellularAutomatonSimulation} instance for a given automaton.
      *
-     * @param width         an {@code int} representing the number of columns
-     * @param height        an {@code int} representing the number of rows
-     * @param defaultState  a state {@code S} used to fill the grid when using
-     *                      the clear action
-     * @param randomState  a generator of states {@code} used to fill the grid
-     *                      when using the reset action
+     * @param automaton         a description of the {@link CellularAutomaton}
      */
-    public CellularAutomatonSimulation(int width, int height, S defaultState, Supplier<S> randomState) {
-        this.grid = new CellGrid<>(width, height, defaultState);
-        this.defaultState = defaultState;
-        this.randomState = randomState;
-        grid.fillRandomly(randomState);
+    public CellularAutomatonSimulation(CellularAutomaton<S> automaton, Random generator) {
+        this.automaton = automaton;
+        this.grid = new Matrix<>(
+                automaton.numberOfColumns(),
+                automaton.numberOfRows(),
+                new ConstantCellInitializer<>(automaton.defaultState())
+        );
+        this.generator = generator;
     }
 
-
+    /**
+     * Goes through each {@link Cell} in this {@code CellGrid} and sets it states with a
+     * state obtained from the supplier.
+     *
+     * @param generator {@link Random} instance used to generate a random state for each cell
+     *                  {@link Cell}.
+     */
+    public void fillRandomly(Random generator) {
+        for (Cell<S> cell : this.grid) {
+            cell.set(this.automaton.randomState(generator));
+        }
+    }
 
     @Override
     public int numberOfColumns() {
-        return this.grid.getNumberOfColumns();
+        return this.grid.width();
     }
 
     @Override
     public int numberOfRows() {
-        return this.grid.getNumberOfRows();
+        return this.grid.height();
+    }
+
+    public Cell<S> at(Coordinate coordinate) {
+        return this.grid.get(coordinate);
     }
 
-    /**
-     * Transitions into the next generationNumber.
-     */
-    @Override
     public void updateToNextGeneration() {
-        this.grid.updateToNextGeneration();
         this.generationNumber.set(getGenerationNumber() + 1);
+        Matrix<S> nextStates = this.nextGenerationMatrix();
+        for (Coordinate coordinate : this.grid.coordinates()) {
+            this.at(coordinate).set(nextStates.get(coordinate));
+        }
+    }
+    /** Computes the {link Matrix} of states obtained after a single step of updates
+     * of the simulation.
+     *
+     * @return the states of each cell after one generation
+     */
+    private Matrix<S> nextGenerationMatrix() {
+        return new Matrix<S>(
+                this.grid.width(),
+                this.grid.height(),
+                new NextGenerationInitializer<>(this)
+        );
     }
-
     @Override
     public void next(Coordinate coordinate) {
-        this.grid.cellAt(coordinate).toggleState();
+        S oldState = this.grid.get(coordinate).get();
+        this.at(coordinate).set(oldState.next());
     }
 
     @Override
     public void copy(Coordinate source, Coordinate destination) {
-        S state = this.grid.at(source).get();
-        this.grid.at(destination).set(state);
+        System.out.println("bip (" + source + ") (" + destination + ")");
+        S state = this.at(source).get();
+        this.at(destination).set(state);
     }
 
     @Override
     public Color getColor(Coordinate coordinate) {
-        return this.grid.at(coordinate).get().getColor();
+        return this.at(coordinate).get().getColor();
     }
 
     @Override
-    public void setChangeListener(Coordinate coordinate, Runnable runnable) {
-        this.grid.cellAt(coordinate).getStateProperty().addListener(
-                (obs,oldV,newV) -> runnable.run()
+    public void setChangeListener(Coordinate coordinate, Runnable listener) {
+        this.at(coordinate).addOnChangeListener(
+                (oldValue, newValue) -> listener.run()
         );
     }
 
@@ -107,7 +133,9 @@ public class CellularAutomatonSimulation<S extends State<S>>
      * Clears the current game.
      */
     public void clear() {
-        this.grid.clear(this.defaultState);
+        for (Cell<S> cell : this.grid) {
+            cell.set(this.automaton.defaultState());
+        }
         this.generationNumber.set(0);
     }
 
@@ -116,7 +144,7 @@ public class CellularAutomatonSimulation<S extends State<S>>
      */
     public void reset() {
         this.clear();
-        this.grid.fillRandomly(this.randomState);
+        this.fillRandomly(this.generator);
     }
 
     @Override
diff --git a/src/main/java/model/ConstantCellInitializer.java b/src/main/java/model/ConstantCellInitializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..43edd965d7b331c4ff1a3a590836e8eb79069d42
--- /dev/null
+++ b/src/main/java/model/ConstantCellInitializer.java
@@ -0,0 +1,17 @@
+package model;
+
+import datastruct.Coordinate;
+import datastruct.MatrixInitializer;
+
+public class ConstantCellInitializer<T>  implements MatrixInitializer<Cell<T>> {
+    private final T defaultValue;
+
+    public ConstantCellInitializer(T defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+
+    @Override
+    public Cell<T> initialValueAt(Coordinate coordinate) {
+        return new Cell<>(defaultValue);
+    }
+}
diff --git a/src/main/java/model/NextGenerationInitializer.java b/src/main/java/model/NextGenerationInitializer.java
index 787a3791dc7a69dce1e569cb014b3f1e3fb0a240..f344e93ff3a3ecf0bf6493603abe3e80d71e3d26 100644
--- a/src/main/java/model/NextGenerationInitializer.java
+++ b/src/main/java/model/NextGenerationInitializer.java
@@ -1,6 +1,7 @@
 package model;
 
 import datastruct.Coordinate;
+import datastruct.Matrix;
 import datastruct.MatrixInitializer;
 
 import java.util.ArrayList;
@@ -8,19 +9,38 @@ import java.util.List;
 
 public class NextGenerationInitializer<S extends State<S>> implements MatrixInitializer<S> {
 
-    private final CellGrid<S> grid;
+    private final CellularAutomatonSimulation<S> simulation;
 
-    public NextGenerationInitializer(CellGrid<S> grid) {
-        this.grid = grid;
+    public NextGenerationInitializer(CellularAutomatonSimulation<S> simulation) {
+        this.simulation = simulation;
     }
 
     @Override
     public S initialValueAt(Coordinate coordinate) {
         List<State<S>> neighbours = new ArrayList<>();
         for (Coordinate neighbourCoord : coordinate.orthodiagonalNeighbours()) {
-            neighbours.add(this.grid.cellAtWrapped(neighbourCoord).getState());
+            Coordinate wrapped = wrap(neighbourCoord);
+            neighbours.add(this.simulation.at(wrapped).get());
         }
-        S state = this.grid.cellAt(coordinate).getState();
+        S state = this.simulation.at(coordinate).get();
         return state.update(neighbours);
     }
+
+    private Coordinate wrap(Coordinate coordinate) {
+        return new Coordinate(
+                modulo(coordinate.x(),this.simulation.numberOfColumns()),
+                modulo(coordinate.y(),this.simulation.numberOfRows())
+        );
+    }
+
+    /** The non-negative remainder of n divided by d.
+     *
+     * @param n an arbitrary integer.
+     * @param d a non-zero integer.
+     * @return the remainder of {@code n/d}, between {@code 0} and {@code n-1}.
+     */
+    private static int modulo(int n, int d) {
+        int result = n % d;
+        return n < 0 ? result + d : result;
+    }
 }
diff --git a/src/main/java/model/OnChangeListener.java b/src/main/java/model/OnChangeListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc72432218567f609aee3de21867aa2c342d6fdc
--- /dev/null
+++ b/src/main/java/model/OnChangeListener.java
@@ -0,0 +1,5 @@
+package model;
+
+public interface OnChangeListener<T> {
+    void valueChanged(T oldValue, T newValue);
+}
diff --git a/src/main/java/model/automata/AbstractAutomaton.java b/src/main/java/model/automata/AbstractAutomaton.java
new file mode 100644
index 0000000000000000000000000000000000000000..818197ea65111fa8b59df1fbbaa6fb75691b4d04
--- /dev/null
+++ b/src/main/java/model/automata/AbstractAutomaton.java
@@ -0,0 +1,24 @@
+package model.automata;
+
+import model.CellularAutomaton;
+import model.State;
+
+public abstract class AbstractAutomaton<S extends State<S>> implements CellularAutomaton<S> {
+
+    private final int numberOfColumns;
+    private final int numberOfRows;
+
+
+    protected AbstractAutomaton(int numberOfColumns, int numberOfRows) {
+        this.numberOfColumns = numberOfColumns;
+        this.numberOfRows = numberOfRows;
+    }
+
+    public int numberOfColumns() {
+        return numberOfColumns;
+    }
+
+    public int numberOfRows() {
+        return numberOfRows;
+    }
+}
diff --git a/src/main/java/model/automata/BiColorAutomaton.java b/src/main/java/model/automata/BiColorAutomaton.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a1cb11974610f963918a930efdd1b572886310d
--- /dev/null
+++ b/src/main/java/model/automata/BiColorAutomaton.java
@@ -0,0 +1,25 @@
+package model.automata;
+
+import model.CellularAutomaton;
+
+import java.util.Random;
+
+public class BiColorAutomaton extends AbstractAutomaton<BiColorState> {
+
+    public BiColorAutomaton(int numberOfColumns, int numberOfRows) {
+        super(numberOfColumns, numberOfRows);
+    }
+
+    @Override
+    public BiColorState defaultState() {
+        return BiColorState.DEAD;
+    }
+
+    @Override
+    public BiColorState randomState(Random generator) {
+        return generator.nextBoolean()? BiColorState.DEAD:
+                generator.nextBoolean()? BiColorState.RED:
+                        BiColorState.BLUE;
+    }
+
+}
diff --git a/src/main/java/model/states/BiColorState.java b/src/main/java/model/automata/BiColorState.java
similarity index 82%
rename from src/main/java/model/states/BiColorState.java
rename to src/main/java/model/automata/BiColorState.java
index de0b791cf798b10b9a27b7d24582a63063b1cfec..bdeb690e2ddc48f4020b803ed69b0ebb8f28f281 100644
--- a/src/main/java/model/states/BiColorState.java
+++ b/src/main/java/model/automata/BiColorState.java
@@ -1,4 +1,4 @@
-package model.states;
+package model.automata;
 
 import javafx.scene.paint.Color;
 import model.State;
@@ -50,12 +50,4 @@ public enum BiColorState implements State<BiColorState> {
                 DEAD;
     }
 
-
-    private final static Random generator = new Random();
-
-    public static BiColorState random() {
-        return generator.nextBoolean()? DEAD:
-                generator.nextBoolean()? RED:
-                        BLUE;
-    }
 }
diff --git a/src/main/java/model/automata/BriansBrainAutomaton.java b/src/main/java/model/automata/BriansBrainAutomaton.java
new file mode 100644
index 0000000000000000000000000000000000000000..f78771a7e5bb3ee4bd8dc9dfcc526cecb8331bff
--- /dev/null
+++ b/src/main/java/model/automata/BriansBrainAutomaton.java
@@ -0,0 +1,22 @@
+package model.automata;
+
+import java.util.Random;
+
+public class BriansBrainAutomaton extends AbstractAutomaton<BriansBrainState> {
+
+    public BriansBrainAutomaton(int numberOfColumns, int numberOfRows) {
+        super(numberOfColumns, numberOfRows);
+    }
+
+    @Override
+    public BriansBrainState defaultState() {
+        return BriansBrainState.OFF;
+    }
+
+    @Override
+    public BriansBrainState randomState(Random generator) {
+        return generator.nextInt(10) == 0 ?
+                 BriansBrainState.ON:
+                 BriansBrainState.OFF;
+    }
+}
diff --git a/src/main/java/model/states/BriansBrainState.java b/src/main/java/model/automata/BriansBrainState.java
similarity index 86%
rename from src/main/java/model/states/BriansBrainState.java
rename to src/main/java/model/automata/BriansBrainState.java
index a90286c47b4371a30e3ed7aa37a08d07f203250d..1f831b884bf0f3e64ba7115a9be31fe1ec350da9 100644
--- a/src/main/java/model/states/BriansBrainState.java
+++ b/src/main/java/model/automata/BriansBrainState.java
@@ -1,4 +1,4 @@
-package model.states;
+package model.automata;
 
 import javafx.scene.paint.Color;
 import model.State;
@@ -48,10 +48,4 @@ public enum BriansBrainState implements State<BriansBrainState> {
         }
         return count;
     }
-
-    final static Random GENERATOR = new Random();
-
-    public static BriansBrainState random() {
-        return GENERATOR.nextInt(10) == 0 ? ON: OFF;
-    }
 }
diff --git a/src/main/java/model/automata/GameOfLifeAutomaton.java b/src/main/java/model/automata/GameOfLifeAutomaton.java
new file mode 100644
index 0000000000000000000000000000000000000000..cfe2b731614561bf6ed11d8b78e36831038ac9e1
--- /dev/null
+++ b/src/main/java/model/automata/GameOfLifeAutomaton.java
@@ -0,0 +1,24 @@
+package model.automata;
+
+import model.CellularAutomaton;
+
+import java.util.Random;
+
+public class GameOfLifeAutomaton extends AbstractAutomaton<GameOfLifeState> {
+
+    protected GameOfLifeAutomaton(int numberOfColumns, int numberOfRows) {
+        super(numberOfColumns, numberOfRows);
+    }
+
+    @Override
+    public GameOfLifeState defaultState() {
+        return GameOfLifeState.DEAD;
+    }
+
+    @Override
+    public GameOfLifeState randomState(Random generator) {
+        return generator.nextBoolean()?
+                 GameOfLifeState.ALIVE:
+                 GameOfLifeState.DEAD;
+    }
+}
diff --git a/src/main/java/model/states/GameOfLifeState.java b/src/main/java/model/automata/GameOfLifeState.java
similarity index 85%
rename from src/main/java/model/states/GameOfLifeState.java
rename to src/main/java/model/automata/GameOfLifeState.java
index 6378a9224fb3975783bda7b3b67f8b9c0ca39514..8e4e5466832d3331cc851ebded9b4b6e7d7ea27d 100644
--- a/src/main/java/model/states/GameOfLifeState.java
+++ b/src/main/java/model/automata/GameOfLifeState.java
@@ -1,4 +1,4 @@
-package model.states;
+package model.automata;
 
 import javafx.scene.paint.Color;
 import model.State;
@@ -43,8 +43,4 @@ public enum GameOfLifeState implements State<GameOfLifeState> {
         return isAlive ? ALIVE : DEAD;
     }
 
-    private static final Random randomGen = new Random();
-    public static GameOfLifeState random() {
-        return randomGen.nextBoolean() ? ALIVE : DEAD;
-    }
 }
diff --git a/src/main/java/model/automata/SeedsAutomaton.java b/src/main/java/model/automata/SeedsAutomaton.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a9b4a3ba054933b21010e93b1e9e795dd9f4436
--- /dev/null
+++ b/src/main/java/model/automata/SeedsAutomaton.java
@@ -0,0 +1,21 @@
+package model.automata;
+
+import java.util.Random;
+
+public class SeedsAutomaton extends AbstractAutomaton<SeedsState> {
+    public SeedsAutomaton(int numberOfColumns, int numberOfRows) {
+        super(numberOfColumns, numberOfRows);
+    }
+
+    @Override
+    public SeedsState defaultState() {
+        return SeedsState.OFF;
+    }
+
+    @Override
+    public SeedsState randomState(Random generator) {
+        return generator.nextInt() == 0?
+                SeedsState.ON:
+                SeedsState.OFF;
+    }
+}
diff --git a/src/main/java/model/states/SeedsState.java b/src/main/java/model/automata/SeedsState.java
similarity index 75%
rename from src/main/java/model/states/SeedsState.java
rename to src/main/java/model/automata/SeedsState.java
index 08953724104aace1e7479d609265d7cc1cd4061e..ebfe4c36201d712956b74de5cbcaedb6b258a5a1 100644
--- a/src/main/java/model/states/SeedsState.java
+++ b/src/main/java/model/automata/SeedsState.java
@@ -1,12 +1,11 @@
-package model.states;
+package model.automata;
 
 import javafx.scene.paint.Color;
 import model.State;
 
 import java.util.List;
 
-import static model.states.BriansBrainState.GENERATOR;
-import static model.states.BriansBrainState.countList;
+import static model.automata.BriansBrainState.countList;
 
 public enum SeedsState implements State<SeedsState> {
     ON, OFF;
@@ -34,7 +33,4 @@ public enum SeedsState implements State<SeedsState> {
         };
     }
 
-    public static SeedsState random() {
-        return GENERATOR.nextInt(10)==0? ON: OFF;
-    }
 }