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 withbw::no-crate-root. - Every other Rust file is a module the crate declares with
mod name;:/src/cards.rsformod cards;,/src/cards/deck.rsformod deck;insidecards. A file nomodreaches is warningbw::unused-file. A module only the tests declare, such as#[cfg(test)] mod tests;, is reached when the game has a#[test]. The build then compiles the tests too. The build reportsbw::unused-fileonly when the game logic builds without an error and its tests compile. - 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. - The catalog of the game's default locale, such as
/src/i18n/en.json, goes into the build too, somsg!can check each message against it (Log lines). A change to it builds the game again. The other locales' catalogs never do. - At most 200 files, 256 KiB per file and 2 MiB in total, data files and the default catalog 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. A change to the default catalog that takes the build sources over the file count or the total is refused the same way.
Catalogs
A game's catalogs, /src/i18n/<locale>.json, hold its messages in each locale. Their paths, limits and checks are in Translations.
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 |
|---|---|---|
INVALID_IMAGE |
upload_art, upload_marketing_image |
The image data is incomplete or unreadable. Upload a complete JPEG or PNG file. |
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, the default catalog's included. |
INVALID_CATALOG |
write_file, patch_file, rename_file |
A catalog Boardweaver could never use (Catalogs). The message names the file and why. |
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, or a catalog cannot be used (Catalogs). |
CATALOG_PLACEHOLDERS_MISMATCH |
commit |
A translation's message places other placeholders, tags or select keys than the same message in the default catalog (Translations). The message names each file, key and both sets of placeholders. Nothing was built. |
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. |
LOCALE_NOT_IN_GAME |
start_game, render_game |
locale is not the game's default locale, a locale it has a catalog for, or en-XA. Write /src/i18n/<locale>.json, then start a new session. |
RENDER_TOO_LARGE |
render_game |
The HTML and CSS are over 100,000 characters together, so the answer holds neither. Render with format: "image". |
UNSUPPORTED_ON_THIS_VERSION |
save_checkpoint, start_game, set_state, render_game |
The tool does not take a v3 session, or start_game or set_state was given validateTypes. On a framework v1 or v2 game, start_game and render_game answer it for locale. |
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 of fuel, about one per WebAssembly instruction. play_bots keeps its bots to half of it (Testing a bot) |
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 |
bw::test-fuel names the test that ran out. Every step a test applies, and every bot call, uses fuel. Play fewer decisions or fewer games in that test, or split it into several tests.
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 and 8 KiB as JSON for all of them | GAME_FAILED: table.log panics |
| A message: a log line's, an offer's label or a refusal's reason | a key of 1 to 128 bytes, messages nested at most 8 deep, no value named player, and only seated players |
GAME_FAILED: table.log, the offers or the refusal 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.
