Have more questions? Join our Discord

Builds, limits and errors

validate_code and commit build the game and run its unit tests. This section lists what a build accepts, the errors it answers, the limits of a test run, and the limits of a match.

Source files

  • The crate root is /src/lib.rs. Without it the build fails with bw::no-crate-root.
  • Every other Rust file is a module the crate declares with mod name;: /src/cards.rs for mod cards;, /src/cards/deck.rs for mod deck; inside cards. A file no mod reaches is warning bw::unused-file.
  • Paths use lowercase letters, digits and _, start with a letter or _, end in .rs, and are at most 8 directories deep.
  • JSON the game logic reads goes in /src/data/. See Data files.
  • At most 200 files, 256 KiB per file and 2 MiB in total, data files included.

write_file, patch_file and rename_file refuse a .rs path, a data file path or a size the build can never accept, with UNBUILDABLE_RUST_SOURCE.

Crates

A game may use exactly three crates: boardweaver_sdk, serde and serde_json. They are already in scope by name. Use serde's derive through the SDK:

use boardweaver_sdk::serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
#[serde(crate = "boardweaver_sdk::serde")]
struct Hand {
    cards: Vec<String>,
}

There is no Cargo.toml to edit. Write Rust 1.98.1, edition 2024.

Words the build refuses

The build refuses these words anywhere in a .rs file, tests included, even as your own names:

Refused Write instead
static, thread_local Keep the value in the state, or make it a const.
unsafe Safe Rust. The SDK gives a game everything it needs.
extern Nothing: the three crates are already in scope.
env, option_env Another name, such as environment.
include, include_str, include_bytes A data file read with data!, a const in the source, or a module file with mod.
asm, global_asm, naked_asm Rust.

Also refused: mod inside a macro, #[path], #[should_panic], crate-level #![...] attributes other than allow, warn, deny, forbid, expect and doc, and brackets nested deeper than 256. The 'static lifetime is allowed.

Reading a build error

validate_code answers errors and warnings as text in the Rust compiler's format, with paths as you wrote them:

error[bw::refused]: a game may not declare a `static`
 --> /src/lib.rs:12:1
   |
12 | static COUNT: u32 = 0;
   | ^^^^^^
   = help: A game is a pure function of its state, the action and the seed, so nothing may outlive a call. Keep the value in a field of the match's state, or use a `const` or a function; for a lookup table, build a `BTreeMap` where you need it rather than caching it

Every bw::refused error ends with a help line that says what to write instead.

A failed commit answers BUILD_FAILED with the first 20 errors. Fix them from the top: later errors often follow from the first.

Code Means
E...., a lint name the Rust compiler's own error or warning
bw::refused a refused word, above
bw::lex a file does not read as Rust tokens
bw::no-crate-root no /src/lib.rs
bw::unused-file a file no mod reaches (warning)
bw::read-outside-source the code refers to a file outside the game's .rs and data files
bw::data-json a data file is not JSON (Data files)
bw::module-too-large the built game is over 4 MiB
bw::bad-module the built game exports no game: check for export_game!
bw::test-failed a unit test panicked or returned an Err; the error points at the panic's line and quotes its message (Testing a game)
bw::test-fuel a unit test used all its computation, or the tests used all of theirs and the rest did not finish, below
bw::test-trap a unit test stopped another way, such as running out of memory, or the tests ran out of time, below
bw::too-many-tests the game logic has more than 200 unit tests, or their names are over 256 KiB, so none ran
bw::client-types the types listed in client_types! do not read, or their JSON Schema is over 512 KiB; the message names the problem, such as two types sharing one name or a type that refers to one no client_types! defines (Client types)
bw::time-limit the build ran past its time limit
bw::memory-limit the build ran out of memory
bw::truncated more than 200 diagnostics; only the first are shown

Tool errors

Code Tool Means
GAME_NOT_FOUND every tool whose input requires gameDefinitionId, and save_checkpoint The game does not exist, was deleted, or your role on it does not reach the tool. Boardweaver gives all three the same answer.
UNBUILDABLE_RUST_SOURCE write_file, patch_file, rename_file A .rs path, a data file path or a size the build cannot accept.
BUILD_FAILED commit, start_game The game logic did not build, a unit test failed, or a client type's name cannot be exported from boardweaver/game (Client types). For commit only, the client did not build.
BUILD_BUSY validate_code, commit, start_game Boardweaver is building other games. Try again after the time it names.
BUILD_UNAVAILABLE validate_code, commit, start_game Boardweaver cannot build games right now. Try again later.
NOT_CONFIGURED validate_code, commit, start_game This Boardweaver environment cannot build games.
TYPE_CHECK_BUSY validate_code Boardweaver is type-checking other games. Nothing changed. Try again in a moment.
INVALID_STATE start_game, set_state The state is not one a session can hold. The message names each problem.
INVALID_ACTION apply_action The action is not a v3 action. Copy one offer's action.
ACTION_REFUSED apply_action Boardweaver or the game refused a step, for the reason the message gives. Nothing changed.
DECISION_IN_PROGRESS apply_action Another player has an open decision. End it, or drop it with set_state.
INIT_FAILED, APPLY_FAILED, REFRESH_FAILED start_game, apply_action, set_state The game logic failed, for example with a panic or a timeout. The message has what the game printed.
GAME_RUNNER_UNAVAILABLE start_game, apply_action, set_state Boardweaver cannot reach its game runner. Nothing changed. Try again in a minute.
GAME_RUNNER_BUSY start_game, apply_action, set_state Boardweaver's game runner is busy with other games. Nothing changed. Try again in a moment.
SESSION_CHANGED apply_action, set_state Another call changed the session while this one ran, so this call changed nothing. Read it with inspect_state, then try again.
RENDER_UNSUPPORTED render_game The session has no client to render: it did not build, or the game has none. start_game's warnings says which.
UNSUPPORTED_ON_THIS_VERSION save_checkpoint, start_game, set_state The tool does not take a v3 session, or start_game or set_state was given validateTypes.

Test limits

Every build runs the unit tests with these limits:

Limit Value When it is hit
Tests 200, with names of at most 256 KiB in all bw::too-many-tests, and no test runs
Computation per test 10,000,000,000 units, enough for play_bots to play a game bw::test-fuel
Computation for all the tests 40,000,000,000 units bw::test-fuel, and the rest do not finish
Memory per test 50 MiB, as in a match bw::test-trap
Time the whole build, tests included, ends 140 seconds after it starts bw::test-trap, and the rest do not run

Limits in a match

Each call to a game function has these limits:

Limit Value When it is hit
Memory 50 MiB GAME_FAILED
Computation a fixed budget per call, which a long loop or a deep search can use up EXECUTION_TIMEOUT
Time about 4 seconds per call EXECUTION_TIMEOUT
State 1 MiB as JSON GAME_FAILED
The offers and changes of one call 2 MiB as JSON GAME_FAILED
Log lines of one step, or of the opening 32 lines, 32 segments per line, and 8 KiB as JSON for all of them GAME_FAILED: table.log panics

A panic in the game logic is GAME_FAILED, with the panic message and any text the game logic printed. Each failure is recorded as a match error, which the game's studio lists.