Command line reference
spimbot [OPTIONS] [BOTS]...
spimbot <COMMAND>
With no command, spimbot runs gui with the same options. A build without the gui feature has no gui command.
Every command takes -h for a summary and --help for the full help. spimbot -V or --version prints the version.
A bot is named after its file without the extension: bots/alice.s plays as alice.
Exit codes
#- 0: success.
gradeexits with 0 whatever the marks. - 1: any failure, such as a program that doesn't assemble, a file that can't be read or written, or a replay that diverges.
execexits with the program's own exit code. - 2: a usage error, such as an unknown option, a missing argument or an invalid value. In a build without the
guifeature,spimbotwith no command prints the help and exits with 2.
Errors
#A failure prints spimbot: and the error to standard error, then a caused by: line for each underlying cause:
$ spimbot run missing.s
spimbot: could not read missing.s
caused by: No such file or directory (os error 2)
When a program doesn't assemble, each error goes to standard error with its file, line and column:
$ spimbot check bad.s
error: `add` takes 3 operands, found 2
--> bad.s:3:2
|
3 | add $t0, $t1
| ^^^
Match options
#spimbot, gui and run take these options:
| Option | Default | Meaning |
|---|---|---|
--seed <SEED> |
random | Seed of the match's random generator |
--mode <MODE> |
normal |
Lab conditions the match runs under |
--cycles <CYCLES> |
10000000 |
Cycle limit, or 0 for none |
--tournament |
off | Use tournament rules: syscalls do nothing, and an exception other than an interrupt crashes the bot, which forfeits the match |
| Mode | Conditions |
|---|---|
normal |
Ordinary match |
test |
Development run with full paint |
part1 |
Lab part 1, with full paint |
part2 |
Lab part 2, with puzzles |
qualification |
Qualification round |
onboarding |
Onboarding assignment |
The same seed, mode, limits and programs always play the same match, unless a bot uses the file syscalls without --tournament. run prints the seed, grade prints it without --json, and the debugger shows it in its title. Modes describes what each mode changes.
gui
#spimbot gui [OPTIONS] [BOTS]...
--seed,--mode,--cycles,--tournament: the match options.--run: start running the match as soon as the bots load.
Opens the debugger on a match between up to two bot files, bot 0 first. Run > Match settings… changes the match options while the window is open.
run
#spimbot run [OPTIONS] <BOTS>...
| Option | Default | Meaning |
|---|---|---|
--seed, --mode, --cycles, --tournament |
The match options | |
--replay <REPLAY> |
Save a replay (.spr) |
|
--png <PNG> |
Save the final map as a PNG | |
--video <VIDEO> |
Record a video (.mp4, .webm or .gif). Needs ffmpeg on PATH |
|
--recording <RECORDING> |
Save a recording (.spv) to watch in a browser |
|
--every <EVERY> |
see meaning | Cycles per frame, at least 1. A video defaults to a thousandth of the cycle limit (10,000 with no limit), a recording to 5,000 |
--grid |
off | Draw the map's grid and pixel coordinates in the PNG and the video. Recordings never show it |
--console |
off | Print each bot's console output as [bot N] line, to standard error with --json |
--json |
off | Print the result as JSON |
Runs a match between one or two bot files, bot 0 first, and prints the seed, each bot's score and status, the winner and the cycles the match ran. run has no console input, so a bot that reads from its console waits forever.
check
#spimbot check [OPTIONS] <FILES>...
--bare: accept only real instructions, as the bare machine does.--fp64: allow odd registers as 64-bit floating-point operands.
Assembles the files as one program with the startup code and the default exception handler. It prints nothing when the program assembles, and otherwise prints every assembly error.
exec
#spimbot exec [OPTIONS] <FILES>... [-- <ARGS>...]
| Option | Default | Meaning |
|---|---|---|
--bare |
off | Accept only real instructions, as the bare machine does |
--fp64 |
off | Allow odd registers as 64-bit floating-point operands |
--delayed-branches |
off | Run the instruction after each branch or jump before the transfer |
--delayed-loads |
off | Deliver each loaded value one instruction late |
--cycles <CYCLES> |
0 |
Cycle limit, or 0 for none |
Assembles the files as one program and runs it without the game, with its console on standard input and output. argv holds the first file's path, then the arguments after --. exec exits with the program's exit code, or prints an error and exits with code 1 when the program reaches the cycle limit or stops any other way.
replay info
#spimbot replay info [OPTIONS] <FILE>
--json: print the result as JSON.
Prints the seed, mode, limits, bots, console input count, end cycle and outcome of a replay without running its programs.
replay verify
#spimbot replay verify [OPTIONS] <FILE>
--json: print the result as JSON.
Re-runs the programs in a replay and compares the recorded checksums, end state and outcome with the re-run. Open only replays you trust. It prints Matches the replay through cycle N, or prints Diverged: and the first difference and exits with code 1, also with --json.
export
#spimbot export [OPTIONS] <REPLAY> <OUTPUT>
--every <EVERY>: cycles per frame, at least 1, with the same defaults asrun.--scale <SCALE>: pixels per world unit of a PNG or video, 2 by default.--grid: draw the map's grid and pixel coordinates in a PNG or video. Recordings never show it.
Re-runs the programs in a replay and writes, by the output's extension:
.png: the map at the replay's end..mp4,.webmor.gif: a video, which needsffmpegonPATH..spv: a recording.
A replay taken before its match ended exports only as a PNG.
tournament
#spimbot tournament [OPTIONS] <BOTS> <BOTS>...
| Option | Default | Meaning |
|---|---|---|
--seeds <SEEDS> |
1 |
Seeds each pair plays in both orders, counting from seed 0 |
--mode <MODE> |
normal |
Lab conditions the matches run under |
--cycles <CYCLES> |
10000000 |
Cycle limit of each match, or 0 for none |
--jobs <JOBS> |
one per CPU core | Matches to run at once. Any value gives the same results |
--replays <REPLAYS> |
Directory to save each replay in, as N-a-vs-b-seedS.spr for match N. Created if needed |
|
--json |
off | Print the result as JSON |
Checks that every bot assembles and loads, then plays every pair of bots under tournament rules, once with each bot as bot 0 for each seed. It prints Match N of M: a vs b, seed S… to standard error as each match starts, then the standings, ranked by wins, then points (the sum of the bot's scores), then name.
grade
#spimbot grade [OPTIONS] --part <PART> <BOT>
| Option | Default | Meaning |
|---|---|---|
--part <PART> |
required | Lab part to grade: part1, part2, onboarding or qualification |
--against <AGAINST> |
Opponent's file, as bot 1 | |
--seed <SEED> |
random | Seed of the match's random generator |
--json |
off | Print the grade as JSON |
--image |
off | Add the final map to the JSON as a PNG. Requires --json |
Runs a match in the mode named after the part, with a cycle limit of 10,000,000, or 300,000 for onboarding. The bot plays as bot 0, without tournament rules. grade prints the seed, then each test's points, rounded to six decimal places, with details for any test short of full marks, then the total.
completions
#spimbot completions <SHELL>
Prints a completion script for bash, elvish, fish, powershell or zsh to standard output.
JSON output
#With --json, run, replay info, replay verify, tournament and grade print one JSON object on standard output, and progress lines and console output go to standard error. A winner is the winning bot's index, or null for a tie.
run --json
#| Field | Type | Meaning |
|---|---|---|
seed |
integer | Seed of the match |
mode |
string | Mode, as named on the command line |
cycles |
integer | Cycles the match ran |
bots |
array | Each bot, bot 0 first: name, score and its status |
winner |
integer or null |
The winner |
{
"seed": 3,
"mode": "normal",
"cycles": 1000000,
"bots": [
{ "name": "spimbot", "score": 0, "status": "running" },
{ "name": "adversary", "score": 48, "status": "running" }
],
"winner": 1
}
replay info --json
#| Field | Type | Meaning |
|---|---|---|
seed |
integer | Seed of the match |
mode |
string | Mode, as named on the command line |
cycle_limit |
integer | Cycle limit, or 0 for none |
cycles_per_tick |
integer | Cycles per game tick |
tournament |
boolean | Whether tournament rules apply |
checksum_interval |
integer | Cycles between the recorded checksums |
bots |
array | Each bot, bot 0 first: name and files, its source file names |
inputs |
integer | Console inputs the replay holds |
end_cycle |
integer | The cycle the replay ends at |
outcome |
object or null |
scores, in bot order, and winner. null for a replay taken before its match ended |
{
"seed": 3,
"mode": "normal",
"cycle_limit": 1000000,
"cycles_per_tick": 1,
"tournament": false,
"checksum_interval": 100000,
"bots": [
{ "name": "spimbot", "files": ["spimbot.s"] },
{ "name": "adversary", "files": ["adversary.s"] }
],
"inputs": 0,
"end_cycle": 1000000,
"outcome": { "scores": [0, 48], "winner": 1 }
}
replay verify --json
#ok: whether the re-run matches the replay.outcome: whenokistrueand the match had ended,scoresandwinner, as inreplay info.divergence: whenokisfalse, the first difference.
{
"ok": false,
"divergence": "checksum mismatch at cycle 200000: expected 0x051506531f10ed36, got 0x051506531f10ed37"
}
tournament --json
#| Field | Type | Meaning |
|---|---|---|
seeds |
integer | Seeds each pair played |
mode |
string | Mode, as named on the command line |
cycle_limit |
integer | Cycle limit of each match, or 0 for none |
matches |
array | Every match in schedule order, each as run --json prints it |
standings |
array | Each bot in ranking order: name, played, won, tied, lost and points |
{
"seeds": 1,
"mode": "normal",
"cycle_limit": 1000000,
"matches": [
{
"seed": 0,
"mode": "normal",
"cycles": 1000000,
"bots": [
{ "name": "spimbot", "score": 0, "status": "running" },
{ "name": "adversary", "score": 32, "status": "running" }
],
"winner": 1
},
{
"seed": 0,
"mode": "normal",
"cycles": 1000000,
"bots": [
{ "name": "adversary", "score": 32, "status": "running" },
{ "name": "spimbot", "score": 0, "status": "running" }
],
"winner": 0
}
],
"standings": [
{ "name": "adversary", "played": 2, "won": 2, "tied": 0, "lost": 0, "points": 64 },
{ "name": "spimbot", "played": 2, "won": 0, "tied": 0, "lost": 2, "points": 0 }
]
}
grade --json
#The object is PrairieLearn's results.json, and nothing else goes to standard output.
| Field | Type | Meaning |
|---|---|---|
gradable |
boolean | Always true |
score |
number | The fraction of the points earned, from 0 to 1, rounded to six decimal places |
tests |
array | Each test in the part's order: name, description, points (earned) and max_points |
images |
array | With --image only: one object with label "final" and url, the final map as a data:image/png;base64, URL |
{
"gradable": true,
"score": 0.832,
"tests": [
{ "name": "Own 100 tiles", "description": "Tiles owned at the end, home base included: 72", "points": 43.2, "max_points": 60 },
{ "name": "Complete 5 trails", "description": "Trails completed: 8", "points": 20.0, "max_points": 20 },
{ "name": "Solve 10 puzzles", "description": "Puzzles solved: 45", "points": 20.0, "max_points": 20 }
]
}
Bot status
#Each bot in run and tournament JSON has a status:
"running": the bot is still running when the match ends."exited": the program exited, withexit_code."crashed": the bot raised an exception under tournament rules.exceptionis its name from the exception table,pcis the faulting instruction's address, andaddr, for an address or bus error only, is the address that faulted. Addresses are JSON numbers.