Skip to content

RossAdrian/swarm-simulator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Swarm Simulator

A deterministic, tick-based, scriptable multi-agent simulation engine on a 2D grid, written in Rust. The engine itself defines no game content — every block type, entity type, and behavior is supplied at runtime as a scenario (JSON) plus a set of scripts (Lua) that implement entity AI, functional-block handlers, and scheduled events.

Given the same scenario and scripts, the engine produces byte-identical output on every run, on any machine. That output is a single, self-contained log file — a full tick-by-tick snapshot of world state — sufficient on its own to drive a separate visualization or analysis tool without ever re-running the simulation.

Status

All engine milestones are complete: world model, blocks/items, entities, ticking, the Lua scripting runtime and action API, the scenario/log file formats, determinism verification, and the spec's worked example as a golden integration test. The visualization application at viewer/ (React + TypeScript + Vite + PixiJS) is also complete — it replays a log file's playback, lifecycle, perception/line-of-sight, and communication data, with inspection, filtering, and search over any tick. See viewer/README.md for its features and commands, and specification/ImplementationPlan.md for the full milestone history and design decisions.

How it works

  1. You write a scenario file (JSON): world dimensions, tunable constants, block/entity class definitions, the initial placement of blocks/items/entities, and any predefined scheduled events.
  2. You write Lua scripts for entity AI and functional-block behavior, referenced by path from the scenario.
  3. swarm-sim loads the scenario, resolves and compiles the scripts, and runs the simulation for a fixed number of ticks. Each tick, in strict order, it: decays item stacks, fires due scheduled events, ticks functional blocks, then ticks entities — all in ascending-ID order for determinism.
  4. The engine writes a single JSON log file containing the input scenario verbatim plus a complete snapshot of every tick, which can be replayed, diffed, or visualized without touching the simulation again.

Entities and functional blocks perceive the world through a sensors table (a windowed, line-of-sight-filtered view) and act through an api.* surface exposing major actions (move, attack, break_block, place, spawn — one per tick) and free actions (eat, pick_up, drop, send_message, pop_message, random, random_int). Scripts run in a locked-down Lua sandbox: no OS/file access, no wall-clock, no unseeded randomness, and a hard instruction budget — a script that errors or exceeds its budget only kills the instance that ran it.

Repository layout

crates/
  swarm-core/   the engine library — world/tick/scripting logic, no I/O
    src/
      world.rs        world grid, coordinates, border (spec ch. 3)
      block.rs        block classes, categories, breaking, loot (spec ch. 4)
      item.rs         items, item stacks, pickup/drop, despawn (spec ch. 5)
      entity.rs       entities, adjacency, hunger/health, perception (spec ch. 6)
      tick.rs         the tick executor and phase order (spec ch. 7)
      ids.rs          monotonic ID counters (spec ch. 8)
      scripting/      Lua sandbox, calling conventions, action API (spec ch. 9)
      scenario.rs     scenario JSON deserialization & validation (spec ch. 10)
      log.rs          output log JSON format (spec ch. 11)
      rng.rs          shared deterministic RNG (SplitMix64)
  swarm-cli/    the `swarm-sim` binary — thin CLI wiring over swarm-core
    tests/
      worked_example.rs   golden integration test (spec Appendix A)
      determinism.rs      repeated-run determinism regression test
specification/
  swarm-simulator-spec.tex   the authoritative formal spec (source of truth)
  swarm-simulator-spec.pdf   rendered copy of the above
  draft-summary.md           informal precursor design notes
  brainstorm.md               original raw brainstorm (historical only)
  ImplementationPlan.md       milestone plan, decisions log, and rationale
  FeatureDescription_visualization_application.md   viewer/ requirements
viewer/
  the visualization app — a standalone npm project (React + TypeScript +
  Vite + PixiJS) that replays a log file; see viewer/README.md
scenarios/
  ready-to-run example scenarios (JSON + Lua scripts) — see "Sample
  scenarios" below

The formal specification (specification/swarm-simulator-spec.tex) is the single source of truth for engine behavior. Its chapter order — World Model, Blocks, Items, Entities, Ticking, IDs, Scripting Runtime, Scenario Format, Log Format, Determinism, Visualization Contract, Worked Example — is also the intended build order, tracked milestone-by-milestone in specification/ImplementationPlan.md.

Building and running

Requires a Rust toolchain (stable) and no other system dependencies — Lua 5.4 is vendored via mlua.

cargo build --workspace
cargo test --workspace

cargo run -p swarm-cli -- <scenario.json> <output.json> <ticks> [--memory] [--messages]
  • <scenario.json> — path to a scenario file (see crates/swarm-cli/tests/fixtures/worked_example/scenario.json for a complete worked example, or spec ch. 10 for the format).
  • <output.json> — where to write the tick-by-tick log.
  • <ticks> — number of ticks to simulate.
  • --memory — optionally include each entity's/functional block's private memory table in the log (omitted by default).
  • --messages — optionally include each messages sent between entities in the log (omitted by default).

Sample scenarios

scenarios/ holds ready-to-run example scenarios, each a self-contained directory with its own scenario.json and scripts/:

  • foraging-ants — three ants wander a 6x6 grid scattered with berry bushes; each ant moves onto an adjacent bush when it sees one (silently eating it, spec §4.3), otherwise takes a random step.
  • rock-miners — two miners hunt a 7x7 grid for rocks, breaking each one they find adjacent (spec §4.2's loot-table roll), stepping onto the cleared tile, and picking up the dropped pebbles, before resuming the hunt.

Both exhaust their world's food/ore within ~30-40 ticks, after which entities (having no more food source) slowly starve — run for around 40 ticks to see the interesting behavior:

cargo run -p swarm-cli -- scenarios/foraging-ants/scenario.json foraging.output.json 40 --memory
cargo run -p swarm-cli -- scenarios/rock-miners/scenario.json mining.output.json 40 --memory

Useful commands

Command Purpose
cargo build --workspace build everything
cargo test --workspace run all unit and integration tests
cargo test -p swarm-core <test_name> run a single test
cargo fmt --all format (runs automatically on file edit via a Claude Code hook)
cargo clippy --workspace --all-targets -- -D warnings lint; must be clean before any milestone is considered done

Determinism and replay

Determinism is a hard requirement, not an aspiration: all simulation state that affects output is stored in ID-ordered structures (never raw HashMap iteration), all randomness — both script-driven (api.random) and engine-driven (loot table rolls) — is drawn from one shared seeded RNG stream, and the instruction-budget sandbox never depends on wall-clock timing. crates/swarm-cli/tests/determinism.rs runs a fixture scenario five times end-to-end through the real binary and asserts byte-identical logs.

License

MIT — see LICENSE.

About

A deterministic, tick-based, scriptable multi-agent simulation engine on a 2D grid, written in Rust.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Contributors