Domain Conventions
The Architecture & Schema page shows the shape of the data. This page captures the conventions you cannot infer from a column’s type or name. Each item below has already caused a real bug — keep them in mind when querying or building on the data.
Dice — turns.dice_sorted
Section titled “Dice — turns.dice_sorted”A roll is three dice, each a piece type (pawn, knight, bishop, rook, queen, king). It is stored as the sorted piece letters, cased by the side to move:
- White to move → upper-case, e.g.
BPQ(bishop, pawn, queen). - Black to move → lower-case, e.g.
bpq.
The ingest API accepts dice as numeric piece codes (1=pawn, 2=knight, 3=bishop, 4=rook,
5=queen, 6=king); the server normalizes them to the cased-letter form above before storing, and a
CHECK constraint (chk_dice_sorted_letters) guarantees only letters are ever stored.
Time control — games.time_initial_sec
Section titled “Time control — games.time_initial_sec”Both time_initial_sec and time_increment_sec strictly contain values in seconds.
So a 3+0 game will be stored as (180, 0) and a 1+1 game as (60, 1).
Result and win rate
Section titled “Result and win rate”games.resultis from White’s perspective:1White win,-1Black win,0draw,NULLunknown/unfinished.- A continuation’s win rate is computed for the side to move at that position
(
turns.active_colorcombined withresult). It is therefore White’s rate from the start, but it flips as you drill into deeper, black-to-move positions.
Stakes — GOLD
Section titled “Stakes — GOLD”stake_currency is an in-game currency (GOLD), not an ISO 4217 code, and amounts are whole
numbers. A stake of 0 means a tournament game — surface it as “no stake” rather than 0 GOLD.
Engine strength
Section titled “Engine strength”The bundled Dice Chess engine validates legality but plays greedily and weakly — it is not a “best move” oracle. The analytical reference for “what is good” is the empirical win rate of strong human players, not the engine and not the bots (which are weak as well).
Positions
Section titled “Positions”Positions are de-duplicated by normalized_fen (board + side to move + castling + en passant).
Analytics group continuations by the resulting position (turns.position_after_id), so different
micro-move orderings that reach the same position collapse into a single line.
Turns — passes vs. no-op turns
Section titled “Turns — passes vs. no-op turns”A turn with empty/NULL played_moves has two very different meanings, told apart by whether the
position changed:
- Legitimate pass —
position_after_id <> position_id(the side to move flips). The player rolled only piece-types that cannot move, so the turn auto-passes. A real game event (~188k turns in the current dump). Kept by analytics; it is a valid continuation (its resulting position is the opponent to move). - No-op self-loop —
position_after_id = position_id(identical position, side does not flip because the game ended). The player rolled but never moved — typically a draw agreed or game abandoned/timed-out before the first move (common in tournaments). Always the last turn of the game. This is not a legal move and is excluded from continuations analytics (AND t.position_after_id <> t.position_id).