Skip to content
CS 233 // Spimbot
Pages

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. grade exits 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. exec exits 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 gui feature, spimbot with 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 as run.
  • --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, .webm or .gif: a video, which needs ffmpeg on PATH.
  • .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: when ok is true and the match had ended, scores and winner, as in replay info.
  • divergence: when ok is false, 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, with exit_code.
  • "crashed": the bot raised an exception under tournament rules. exception is its name from the exception table, pc is the faulting instruction's address, and addr, for an address or bus error only, is the address that faulted. Addresses are JSON numbers.