State Transition Notation (STN) Specification
- Version: 1.0.0
- Author: Cyril Kato
- Published: June 13, 2025
- License: Open Web Foundation Agreement 1.0
1. Status of this document
The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are to be interpreted as normative requirements.
Capitalized terms (Position, Board, Square, Hand, First Player Hand, Second Player Hand, Piece, Active Player, Game Protocol, Rule System) are defined in the Glossary. This document does not redefine those terms.
2. Overview
State Transition Notation (STN) is a rule-agnostic, JSON-based format for describing state transitions in abstract strategy board games. STN captures the net changes between any two game Positions by recording modifications across the three Location types defined by the Game Protocol:
- Board Square contents,
- First Player Hand contents,
- Second Player Hand contents,
as well as the Active Player status.
STN uses standardized CELL coordinates for Board Locations and QPI Piece identification for unambiguous Piece references.
STN is purely a difference format — it describes the observable changes between two complete game Positions without encoding how those transitions were achieved.
3. Dependencies
STN builds upon two foundational Sashité specifications:
| Specification | Purpose |
|---|---|
| CELL | Multi-dimensional coordinate encoding for Board Squares |
| QPI | Qualified Piece Identifier for unambiguous Piece identification |
4. Scope
4.1 What STN defines
STN defines:
- a JSON object structure for expressing Position deltas,
- field specifications for Board changes, First Player Hand changes, Second Player Hand changes, and Turn toggle,
- validation rules for the format,
- semantic interpretation of the delta format.
4.2 What STN does not define
STN is deliberately format-only. It does not define:
- how transitions are achieved (that belongs to PMN or Rule Systems),
- whether a transition is legal or valid,
- Game-specific constraints on Piece movements or Captures,
- any evaluation or outcome semantics.
All legality and Game-specific semantics belong to Rule Systems, not to STN.
5. Format specification
5.1 JSON structure
An STN object is a JSON object with four optional fields:
{
"board_diff": {
"<cell-coordinate>": "<qpi-piece>" | null
},
"first_player_hand_diff": {
"<qpi-piece>": <delta>
},
"second_player_hand_diff": {
"<qpi-piece>": <delta>
},
"toggle": <boolean>
}
All fields are optional. Each field represents changes to a distinct aspect of the game Position.
5.2 Grammar (EBNF)
stn-object ::= "{" [ field-list ] "}" ;
field-list ::= field ( "," field )* ;
field ::= board-diff-field
| first-hand-diff-field
| second-hand-diff-field
| toggle-field ;
board-diff-field ::= '"board_diff"' ":" board-diff-object ;
board-diff-object ::= "{" [ board-entries ] "}" ;
board-entries ::= board-entry ( "," board-entry )* ;
board-entry ::= cell-key ":" ( qpi-value | "null" ) ;
cell-key ::= json-string ; (* Must conform to CELL specification *)
qpi-value ::= json-string ; (* Must conform to QPI specification *)
first-hand-diff-field ::= '"first_player_hand_diff"' ":" hand-diff-object ;
second-hand-diff-field ::= '"second_player_hand_diff"' ":" hand-diff-object ;
hand-diff-object ::= "{" [ hand-entries ] "}" ;
hand-entries ::= hand-entry ( "," hand-entry )* ;
hand-entry ::= qpi-key ":" integer-delta ;
qpi-key ::= json-string ; (* Must conform to QPI specification *)
integer-delta ::= json-integer ; (* Must be non-zero *)
toggle-field ::= '"toggle"' ":" json-boolean ;
6. Field specifications
6.1 board_diff field
Type: Object Purpose: Records changes to Piece positions on the Board
Maps CELL coordinates to their final state after the transition:
- Key: CELL coordinate (string, MUST conform to CELL specification)
- Value: QPI Piece identifier (string) or
null(indicating empty Square)
Semantics:
| Condition | Meaning |
|---|---|
| Key present, value is QPI | Square contains the specified Piece after transition |
Key present, value is null |
Square becomes empty after transition |
| Key absent | Square was not affected by the transition |
Example:
{
"board_diff": {
"e2": null,
"e4": "C:P"
}
}
6.2 first_player_hand_diff field
Type: Object Purpose: Records changes to Piece counts in the First Player Hand
Maps QPI Piece identifiers to net count changes in the First Player Hand:
- Key: QPI Piece identifier (string, MUST conform to QPI specification)
- Value: Non-zero integer delta (positive = Pieces added, negative = Pieces removed)
Constraints:
- Values MUST be non-zero integers.
- Positive values indicate Pieces added to the First Player Hand.
- Negative values indicate Pieces removed from the First Player Hand.
Example:
{
"first_player_hand_diff": {
"S:P": -1
}
}
6.3 second_player_hand_diff field
Type: Object Purpose: Records changes to Piece counts in the Second Player Hand
Maps QPI Piece identifiers to net count changes in the Second Player Hand:
- Key: QPI Piece identifier (string, MUST conform to QPI specification)
- Value: Non-zero integer delta (positive = Pieces added, negative = Pieces removed)
Constraints:
- Values MUST be non-zero integers.
- Positive values indicate Pieces added to the Second Player Hand.
- Negative values indicate Pieces removed from the Second Player Hand.
Example:
{
"second_player_hand_diff": {
"c:r": 1
}
}
6.4 toggle field
Type: Boolean
Purpose: Indicates whether the Active Player changes during the transition
Default: false when omitted
| Value | Meaning |
|---|---|
false (or omitted) |
The Active Player remains the same after applying the transition |
true |
The Active Player changes after applying the transition |
Example:
{
"board_diff": { "e2": null, "e4": "C:P" },
"toggle": true
}
7. Relationship to the Game Protocol
STN fields map directly to the three Location types defined by the Game Protocol:
| STN field | Game Protocol Location |
|---|---|
board_diff |
Squares on the Board |
first_player_hand_diff |
First Player Hand |
second_player_hand_diff |
Second Player Hand |
This one-to-one correspondence ensures that any Protocol-level transition involving Piece Displacements across these three Location types can be expressed unambiguously in STN, regardless of the Rule System.
In particular, Board → Hand Displacements (captures) are expressed by combining a board_diff entry (Square becomes empty or gains the moving Piece) with an entry in the Hand diff field corresponding to the Active Player’s Hand, consistently with the capture destination constraint defined in the Game Protocol (§8.4).
8. Semantic interpretation
8.1 Empty object behavior
{}
An empty STN object represents no changes to the Position:
- No Board Squares change.
- No First Player Hand contents change.
- No Second Player Hand contents change.
- The Active Player remains the same (due to default
toggle: false).
This represents scenarios such as position comparisons with identical results, null transformations, or baseline states for cumulative calculations.
8.2 Minimal changes
Simple movement (no Turn change):
{
"board_diff": {
"e2": null,
"e4": "C:P"
}
}
Simple movement (with Turn change):
{
"board_diff": {
"e2": null,
"e4": "C:P"
},
"toggle": true
}
Pass Move (Turn-only change):
{
"toggle": true
}
8.3 Capture
A capture by the First Player (Active Player has Side first): the captured Piece is displaced to the First Player Hand.
{
"board_diff": {
"d4": null,
"d5": "C:R"
},
"first_player_hand_diff": {
"c:p": 1
},
"toggle": true
}
A capture by the Second Player (Active Player has Side second): the captured Piece is displaced to the Second Player Hand.
{
"board_diff": {
"e5": null,
"e4": "c:p"
},
"second_player_hand_diff": {
"C:P": 1
},
"toggle": true
}
8.4 Drop
A Piece Drop from the First Player Hand onto the Board:
{
"board_diff": {
"e5": "S:P"
},
"first_player_hand_diff": {
"S:P": -1
},
"toggle": true
}
8.5 Complex transitions
Multi-Piece movement (e.g., castling):
{
"board_diff": {
"e1": null,
"g1": "C:K",
"h1": null,
"f1": "C:R"
},
"toggle": true
}
Promotion with capture (First Player captures, pawn promotes):
{
"board_diff": {
"e7": null,
"e8": "C:Q"
},
"first_player_hand_diff": {
"c:r": 1
},
"toggle": true
}
Cumulative multi-Move delta:
{
"board_diff": {
"e2": null,
"e4": "C:P",
"e7": null,
"e5": "c:p"
}
}
Net result of two Moves with the original Active Player still active.
9. Validation rules
9.1 Structural validation
An STN document MUST satisfy:
- JSON object — The document MUST be a valid JSON object.
- Known fields only — The object MAY contain
board_diff,first_player_hand_diff,second_player_hand_diff, and/ortogglefields. Unknown fields SHOULD be rejected. - Correct types —
board_diffMUST be an object;first_player_hand_diffMUST be an object;second_player_hand_diffMUST be an object;toggleMUST be a boolean.
9.2 Format validation
An STN document MUST satisfy:
- Valid CELL keys — All keys in
board_diffMUST conform to the CELL coordinate specification. - Valid Board values — Values in
board_diffMUST be valid QPI identifiers ornull. - Valid QPI keys — All keys in
first_player_hand_diffandsecond_player_hand_diffMUST conform to the QPI specification. - Non-zero deltas — All values in
first_player_hand_diffandsecond_player_hand_diffMUST be non-zero integers.
9.3 Semantic validation
Semantic validation is application-specific. Implementations MAY validate:
- QPI identifiers reference valid Piece types for the Game context.
- CELL coordinates reference valid Board Squares for the Game context.
- Hand modifications respect Game-specific constraints.
10. Design properties
STN is intended to be:
- Rule-agnostic — Independent of specific Game mechanics or rules.
- Complete — Can represent any Position-to-Position transition across all three Location types.
- Unambiguous — First Player Hand and Second Player Hand are represented by distinct fields, directly reflecting the Game Protocol’s Location model.
- Efficient — Only records what actually changed.
- Composable — Multiple STN deltas can be combined for cumulative effects.
- Bidirectional — Can be used to calculate reverse transitions.
- Format-independent — Compatible with any Position representation system.
- Pure diff semantics — Empty object means genuinely no changes.
11. Use cases
11.1 Position comparison
// Compare two Positions and generate STN diff
const stn = calculatePositionDiff(positionA, positionB);
11.2 Incremental updates
// Apply STN delta to update Position
const newPosition = applySTN(currentPosition, stnDelta);
11.3 Move validation
// Check if proposed changes are valid
const isValid = validateSTN(currentPosition, proposedSTN);
11.4 Undo/Redo systems
// Store STN deltas for reversible operations
const undoSTN = invertSTN(forwardSTN);
12. JSON Schema
A JSON Schema for STN is published for programmatic validation:
Implementations MAY rely on this schema as a baseline validator and add further semantic checks as needed.
13. Examples
See STN Examples for practical implementation guidance and integration patterns.
14. Reference implementations
The following reference libraries are maintained by Sashité and are intended to be idiomatic, fully tested, and spec-accurate implementations of STN v1.0.0.
They generally provide:
- strict parsing and validation (
valid?,parse, and a raising/bang variant), - clear error reporting for invalid inputs.
If a library behavior appears to conflict with this document, this specification is normative. Please report issues (or propose clarifications) on the relevant repository.
- Ruby — stn.rb
15. License
This specification is made available under the terms of the Open Web Foundation Agreement 1.0 (OWFa 1.0).
The authoritative legal text is the OWF “Final Specification Agreement (OWFa 1.0)”.
