A Redcode assembler and Core War simulator, written in Rust.
dmars.drpz.xyz · browser playground
Core War is the 1984 programming game in which warriors — self-modifying programs written in a pseudo-assembly language called Redcode — battle for control of a circular memory array called the core. The last warrior with a running process wins.
dmars is a reimplementation of pMARS, the canonical
Core War toolchain. The assembler handles the full
ICWS'94 preprocessor and produces load-file
output byte-compatible with pmars -A. The simulator runs battles between assembled
warriors, with ICWS'88 restrictions available behind a flag.
The same core compiles to WebAssembly, which powers the browser playground — write and fight your own warriors, or load any of the 503 classics from the bundled hill corpus.
Shell installer (macOS and Linux):
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/drivasperez/dmars/releases/latest/download/dmars-installer.sh | shCargo:
cargo install --locked --git https://github.com/drivasperez/dmarsPre-built binaries are available on the latest GitHub release.
dmars assemble warrior.red # assemble Redcode into an ICWS'94 load file on stdout
dmars assemble -o warrior.rc warrior.red # write the load file to a path instead
dmars assemble -8 warrior.red # enforce ICWS'88 restrictions (pMARS -8)
dmars run a.red b.red # run warriors against each other in the simulator
dmars run -f -r 100 a.red b.red # fight 100 seeded rounds and report the score
dmars watch a.red b.red # visualise a battle in an interactive terminal UI
dmars --help # full optionsThe CLI follows pMARS conventions throughout — core size, cycle and process limits,
read/write windows, and fixed (--position, pMARS -F) or checksum-seeded (-f)
positioning all behave identically, down to the round-by-round RNG sequence.
When running a single battle, dmars roughly matches pMARS's performance. It is
significantly faster when running many battles: rounds that never read P-space are
provably independent, so dmars run spreads them across every core (warriors using
LDP/STP automatically run serially, preserving pMARS semantics).
500 rounds, Aeka vs Flash Paper, on an Apple M3 Pro — identical tallies both ways
(7 11 482):
| command | time |
|---|---|
pmars -b -f -r 500 aeka.red flashpaper.red |
0.77 s |
dmars run -f -r 500 aeka.red flashpaper.red |
0.10 s (7.5×) |
pMARS 0.9.4 compiled -O3; dmars single-threaded (-j 1) runs the same 500 rounds in
0.78 s.
Build with cargo build; test with cargo t (an alias for
cargo-nextest). Correctness is enforced by an oracle suite: the
vendored pMARS 0.9.4 source (doc/pmars-0.9.4/) is compiled on demand and every battle
outcome, listing, and RNG position sequence is diffed against it. Benchmarks run with
cargo bench, and the website (including the wasm build of the assembler and simulator)
lives in site/.
dmars is licenced with GPL-2.0-or-later, matching pMARS.
dmars is mostly not a direct port of pMARS, but it was written
with the pMARS source open on the other screen, and some of it (notably the positioning
RNG) is a direct port, so it honours the license of the original by Albert Ma, Na'ndor
Sieben, Stefan Strack, and Mintardjo Wangsawidjaja. The vendored pMARS source in
doc/pmars-0.9.4/ retains its own notices. The warriors in warriors/ and
warriors/corpus/ are historical community works by their respective authors, bundled
for testing and for the playground. No copyright is claimed and if any of the authors
request their warrior's removal, I will honour it. But I imagine nobody will mind.
