Sashité for Developers
  1. Sashité for Developers
  2. Specifications
  3. STN
  4. 1.0.0

State Transition Notation (STN) Specification


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:

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:

4.2 What STN does not define

STN is deliberately format-only. It does not define:

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:

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:

Constraints:

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:

Constraints:

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:

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:

  1. JSON object — The document MUST be a valid JSON object.
  2. Known fields only — The object MAY contain board_diff, first_player_hand_diff, second_player_hand_diff, and/or toggle fields. Unknown fields SHOULD be rejected.
  3. Correct typesboard_diff MUST be an object; first_player_hand_diff MUST be an object; second_player_hand_diff MUST be an object; toggle MUST be a boolean.

9.2 Format validation

An STN document MUST satisfy:

  1. Valid CELL keys — All keys in board_diff MUST conform to the CELL coordinate specification.
  2. Valid Board values — Values in board_diff MUST be valid QPI identifiers or null.
  3. Valid QPI keys — All keys in first_player_hand_diff and second_player_hand_diff MUST conform to the QPI specification.
  4. Non-zero deltas — All values in first_player_hand_diff and second_player_hand_diff MUST be non-zero integers.

9.3 Semantic validation

Semantic validation is application-specific. Implementations MAY validate:


10. Design properties

STN is intended to be:


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:

If a library behavior appears to conflict with this document, this specification is normative. Please report issues (or propose clarifications) on the relevant repository.


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)”.