cella_gui 1.0.0

A GUI for the Cella cellular automata library
# Cella

![Cella GUI screenshot](cella.gif)

Cella is a Rust toolkit for cellular automata (CA): grids of cells that
change step by step according to simple local rules, like Conway's Game of
Life. It has four layers, each usable on its own:

- **An engine** for 1D and 2D rule-based CAs, with multi-threaded stepping
  and JSON configs you can save, share and resume.
- **A plugin seam** (`ExternalModel`) for replacing the built-in rules with
  your own transition code. A wildfire spread model ships as the worked
  example.
- **An Explore module** that runs any rule or model many times
  (ensembles), searches for good settings (evolution) and maps the range of
  behaviors a rule family can produce (MAP-Elites).
- **A GUI workbench** (egui) and a small **CLI demo menu** on top of all of
  it.

It is for people who want to play with CA rules, build a model on a fast
grid engine, or study how a stochastic (random-element) model behaves across
many runs.

**Wildfire disclaimer.** The wildfire model and the scoring tools in
[`validation/`](validation/README.md) are a personal-interest project.
They must not be used to model or predict real fires.

---

## Features

- 1D Wolfram-style rules (any code, any radius) and 2D neighborhood-count
  rules (Moore, Von Neumann, Langton, StraightLine, Knight), with
  multi-state cells and optional per-rule randomness.
- Deterministic results: the same config and seed give the same run, on any
  thread count.
- JSON configs: load, save, and resume a run part-way through.
- Plugin models: implement `ExternalModel` in your own crate and tag it
  with `typetag`. Configs then load it by name, and the engine and Explore
  drive it with no changes to Cella. To use it in the GUI, link your crate
  into the `cella` binary.
- Explore: Monte Carlo ensembles (probability maps), genetic-algorithm
  evolution, novelty search and MAP-Elites, for any rule or model.
- GUI: live rule editor, paint/stamp tools, zoom and pan, population
  charts, per-type colors, GIF export, and an Explore tab.
- Wildfire example model with a validation pipeline that scores it against
  observed fires, including null baselines (see `validation/`).

---

## Quick start

### Prerequisites

- **Rust.** Install via [rustup]https://rustup.rs. The GUI crates
  (`eframe`/`egui` 0.35) require Rust **1.92 or newer**. `cella_lib` alone
  uses the 2024 edition, so it needs at least 1.85. The project is developed
  on recent stable.
- **Linux desktop libraries** for the GUI. `eframe` needs the usual X11 or
  Wayland and OpenGL development packages. `rfd`, which draws the file
  open/save dialogs, needs `xdg-desktop-portal` or `zenity`. On Debian or
  Ubuntu, `sudo apt install zenity` covers the dialogs.
- **WSL users:** without a desktop session the "Load Config JSON..." button
  silently does nothing. Install `zenity`, or skip the dialog by passing a
  config on the command line (next section). Details are in
  [docs/app.md, "Troubleshooting"]docs/app.md#troubleshooting.
- **Python 3** is only needed for the data-conversion scripts in
  `validation/`. It is not needed to build or run Cella.

### Build and run

```bash
# Build the binary (first build downloads and compiles dependencies)
cargo build --release

# Launch the GUI
cargo run --release -- --gui

# Launch the GUI with a config already open (also the WSL workaround)
cargo run --release -- --gui --config configs/life.json

# Launch the CLI demo menu
cargo run --release
```

The Cargo package is named `cella_gui` (the name `cella` is taken on
crates.io), but the program it builds is still called `cella`, so the
release build ends up at `target/release/cella`. Use `--package cella_gui`
if a Cargo command asks which package you mean.

Window size is optional:

```bash
cargo run --release -- --gui --size=1280x720
cargo run --release -- --gui --width=1920 --height=1080
```

If only `--width` or `--height` is given, the other is computed for a 16:9
window.

### CLI demo menu

Without `--gui`, the binary shows a numbered menu and prints results to the
terminal:

```
Cella demos (CLI):
1) 2D Game of Life (approx)
2) 1D Wolfram Rule 30 (n=1)
3) 1D Wolfram n=2 demo
4) 1D Custom (Wolfram code + n)
5) Load from configuration file (JSON)
6) Langton's ant (placeholder)
7) 1D three-state cycle demo
8) 2D three-state cycle demo
9) 2D StraightLine neighborhood demo
0) Exit
```

Option 6 is a placeholder: it only prints a "not yet implemented" message,
because Langton's ant needs a moving agent and the engine has none.

To run a config file, pick option 5:

```
Select an option: 5
Enter path to JSON config: configs/life.json
Enter number of steps to run [10]: 20
```

Ready-made configs are in [`configs/`](configs/): Life, Rule 30, multi-state
cycles, other neighborhoods, wildfire demos, and Explore setups.

---

## Documentation map

| Document | Contents |
|----------|----------|
| [Application guide]docs/app.md | CLI, GUI workbench tour, editing, Explore tab, config guide, troubleshooting |
| [Library README]cella_lib/README.md | Using `cella_lib` in your own crate: install, code samples, bundled examples |
| [Library guide]docs/lib.md | Architecture, module reference, rule system, external models, serialization, threading |
| [Explore guide]docs/explore.md | Ensembles, evolution and MAP-Elites for any rule or model; how to read results honestly |
| [Primer: Monte Carlo]docs/primer-monte-carlo.md | Plain-language: why run a simulation many times, probability maps, particle filters, seeds |
| [Primer: Genetic Algorithms]docs/primer-genetic-algorithms.md | Plain-language: populations, selection, mutation, novelty search, MAP-Elites |
| [Validation README]validation/README.md | Scoring the wildfire model against real fires; start with [ANALYSIS.md]validation/ANALYSIS.md |
| [Performance review]docs/performance.md | Developer notes: engine internals, optimizations, known issues |
| [Roadmap]docs/roadmap.md | Developer notes: GUI and plugin-UI work plan, with status per phase |

Rust API docs: run `cd cella_lib && cargo doc --open` for the library.
(`make doc` documents only the `cella_gui` package, because `cella_lib` is
a separate build root; see "Building and testing".)

---

## Using `cella_lib` as a library

The engine is its own crate, `cella_lib`, which you can use in your own
programs without the GUI. Its README covers installation, code samples
(Game of Life from a config, Rule 30 in the terminal), plugging in your own
model, and the bundled example programs:
**[cella_lib/README.md](cella_lib/README.md)**.

### Thread count

The engine steps grids in parallel. To set the worker count, create a
`cella.properties` file in the directory you run from (the repo root has
one already):

```properties
# Number of worker threads for grid stepping. 1 disables parallelism.
threads=4
```

Without the file, the engine uses `std::thread::available_parallelism()`,
usually the number of logical CPUs.

---

## Config format

A config is a JSON file with a `"dim"` field (`"1d"` or `"2d"`), a size, an
`initial` list of cell types, and a `rule` made of subrules. A subrule says
"a cell of type A, seeing at least N neighbors of type B, becomes type C".

<details>
<summary>2D example — Game of Life (<code>configs/life.json</code>)</summary>

```json
{
  "dim": "2d",
  "width": 10,
  "height": 10,
  "history_limit": 5,
  "initial": ["Inactive","Inactive","...","Alive","Alive","Alive","..."],
  "rule": {
    "subrules": [
      { "current_type":"Alive", "criteria_type":"Alive", "count":4,
        "op":"gt", "range":1, "neighborhood":"Moore",
        "randomness":null, "output_type":"Inactive" },
      { "current_type":"Alive", "criteria_type":"Alive", "count":2,
        "op":"gt", "range":1, "neighborhood":"Moore",
        "randomness":null, "output_type":"Alive" },
      { "current_type":"Inactive", "criteria_type":"Alive", "count":3,
        "op":"eq", "range":1, "neighborhood":"Moore",
        "randomness":null, "output_type":"Alive" }
    ]
  }
}
```

</details>

<details>
<summary>1D example — Wolfram Rule 30 (<code>configs/1d_rule30_center.json</code>)</summary>

```json
{
  "dim": "1d",
  "width": 257,
  "history_limit": 4,
  "initial": ["Inactive","...","X","...","Inactive"],
  "rule": {
    "subrules": [
      { "current_type":"X", "criteria_type":"X",
        "wolfram_code":"30", "n":1,
        "randomness":null, "output_type":"X" },
      { "current_type":"Inactive", "criteria_type":"X",
        "wolfram_code":"30", "n":1,
        "randomness":null, "output_type":"X" }
    ]
  }
}
```

</details>

(The `"..."` entries stand in for the full list in the real files. In JSON
`wolfram_code` is a string; in the Rust API it is a number.)

2D subrule notes: `op` (`"lt"`/`"gt"`/`"eq"`) is **inclusive** for `gt` and
`lt` ("at least" / "at most"). `neighborhood` is one of `"Moore"`,
`"VonNeumann"`, `"Langton"`, `"StraightLine"`, `"Knight"`. An optional
`"limit"` turns `gt`/`lt` into an inclusive between-range (for example
`"count":2, "op":"gt", "limit":3` means "survive with 2 to 3 neighbors").
`"randomness"` and `"limit"` may be omitted.

The full field guide, plus the optional `model`, `colors`, `snapshot`,
`ensemble` and `evolve` blocks, is in
[docs/app.md, "Config file guide"](docs/app.md#config-file-guide) and
[docs/lib.md](docs/lib.md).

---

## Building and testing

The `Makefile` wraps the common commands (each target has a one-line
comment above it):

| Command | What it does |
|---------|--------------|
| `make build` / `make build-release` | Build the `cella` binary |
| `make run` / `make run-gui` | Run the CLI menu / the GUI at 1024x768 |
| `make clippy` | Lint everything with warnings as errors (the lint gate) |
| `make fmt` / `make fmt-check` | Format / check formatting |
| `make test` | Fast tests: non-ignored `cella_lib` tests plus the `wildfire_smc` example tests |
| `make test-all` | Also runs the slow `#[ignore]`d tests |
| `make coverage` | Line coverage for `cella_lib` (needs `cargo install cargo-llvm-cov`) |

**`cella_lib` is its own Cargo build root.** The root `Cargo.toml` depends
on it by path but does not list it as a workspace member. In practice:

- A bare `cargo test` at the repo root tests only the `cella` binary, not
  the library. The library tests run with `cd cella_lib && cargo test`,
  which is what `make test` does for you.
- `cella_lib` has its own `target/` directory and its own copy of the
  release profile, so it builds separately from the root.
- Its examples (`cella_lib/examples/`) are built and run from inside
  `cella_lib/`, for example `cd cella_lib && cargo run --release --example
  explore`.

Before sending a change, run `make clippy` and `make test`. More on test
environment variables, snapshots and benchmarks is in
[docs/lib.md, "Building and testing"](docs/lib.md#building-and-testing).

---

## Project layout

```
cella/
├── Cargo.toml          # `cella_gui` package (builds the `cella` app)
├── Makefile            # build / lint / test shortcuts
├── cella.properties    # Thread count
├── configs/            # Ready-made JSON scenarios
├── docs/               # Guides (see the documentation map above)
├── src/                # Binary crate
│   ├── main.rs         #   Entry point: CLI menu or --gui
│   ├── demos/          #   CLI demos
│   └── gui/            #   egui workbench (app, panels, explore, export, ...)
├── cella_lib/          # Library crate (its own Cargo build root)
│   ├── src/
│   │   ├── grid1d.rs, grid2d.rs, rules.rs   # Grids and rule system
│   │   ├── config.rs, state.rs              # JSON configs, save/resume
│   │   ├── external.rs                      # ExternalModel plugin seam
│   │   ├── explore/                         # Ensembles, evolution, MAP-Elites
│   │   └── wildfire/                        # Worked-example model (not engine code)
│   ├── examples/       #   explore, wildfire_validate, wildfire_smc, ...
│   └── tests/          #   Integration and snapshot tests
└── validation/         # Scoring the wildfire model against real fires
```

The full module map for the library is in [docs/lib.md](docs/lib.md); for
the GUI, in [docs/app.md](docs/app.md#for-contributors-gui-code-layout).

---

## License

MIT — see [LICENSE](LICENSE).