Implementing a Rule

How to write a transition function using CellularAutomataRule.

The Transition Function

In JCAL, the transition function (σ) is the core of any cellular automaton. It determines how each cell evolves from one generation to the next.

To define a transition function, extend CellularAutomataRule and implement transition. JCAL calls this method once per cell per generation, passing the current cell and its neighbors. Return a new Cell carrying the cell’s next state — never mutate the input cell.

transition(cell, neighbors) → next cell state

Minimal Example

public class GameOfLifeRule extends CellularAutomataRule {

    private static final CellState DEAD  = new CellState("dead",  "0");
    private static final CellState ALIVE = new CellState("alive", "1");

    @Override
    public Cell transition(Cell cell, List<Cell> neighbors) {
        long aliveCount = neighbors.stream()
            .filter(n -> n.getCurrentStatus().equals(ALIVE))
            .count();

        boolean isAlive = cell.getCurrentStatus().equals(ALIVE);
        Cell next = new Cell(DEAD, cell.getCol(), cell.getRow());

        if (!isAlive && aliveCount == 3) {
            next.setCurrentStatus(ALIVE);       // birth
        } else if (isAlive && (aliveCount == 2 || aliveCount == 3)) {
            next.setCurrentStatus(ALIVE);       // survival
        }

        return next;
    }
}

Running the Automaton

Wire the rule together with a configured grid and call run:

CellularAutomataConfiguration config = new CellularAutomataConfigurationBuilder()
    .setWidth(20).setHeight(20)
    .setTotalIterations(10)
    .setDefaultStatus(DEAD)
    .setNeighborhoodType(NeighborhoodType.MOORE)
    .setInitalState(seedCells)
    .build();

CellularAutomata ca = new CellularAutomata(config);
GameOfLifeRule rule = new GameOfLifeRule();
ca = rule.run(ca);
System.out.println(ca);

run applies the transition function for the configured number of iterations (or indefinitely when setInfinite(true)) and returns the updated CellularAutomata.


Anonymous Rule (Inline)

For quick experiments, you can define the rule inline without a named class:

CellularAutomataRule rule = new CellularAutomataRule() {
    @Override
    public Cell transition(Cell cell, List<Cell> neighbors) {
        // rule logic here
        return new Cell(cell.getCurrentStatus(), cell.getCol(), cell.getRow());
    }
};

Named classes are recommended for any non-trivial rule because they are easier to test, reuse, and document.


Parallel Execution

For large grids, replace CellularAutomataRule with CellularAutomataParallelRule. The transition signature is identical; JCAL distributes the work across threads automatically using Java parallel streams.

public class MyParallelRule extends CellularAutomataParallelRule {
    @Override
    public Cell transition(Cell cell, List<Cell> neighbors) {
        // exact same logic as the sequential version
    }
}

See Parallel Execution for more details and caveats.


The CCA Refinements Hook

For Complex Cellular Automata that need per-cell pre-processing before neighbor lookup, override the refinements method:

@Override
public Cell refinements(Cell cell) {
    // Adjust internal state before neighbors are evaluated this generation
    return cell;
}

See Complex Cellular Automata for a full explanation and example.


See Also