Sashité for Developers

Portable Move Notation (PMN) Specification

Version: 1.0.0 Author: Sashité Published: May 1, 2025 License: MIT License


Overview

Portable Move Notation (PMN) is a rule‑agnostic, JSON‑based format for describing state‑changing actions in abstract‑strategy board games. A PMN record lists those actions sequentially, allowing any engine to reproduce the exact, deterministic transformation of a game position—independent of the rules that validate or forbid such transformations.

PMN deliberately does not embed legality, turn order, or game‑specific concepts such as check, mate, or repetition. It focuses on a minimal yet exhaustive vocabulary for moving, capturing, dropping, promoting, or otherwise transforming pieces on an arbitrary‑dimension board.


Core Concepts

Action Item

An action item is the atomic unit of PMN. Each item is a JSON object with four fields:

{
  "src_square": <string-or-null>,
  "dst_square": <string>,
  "piece_name": <string>,
  "piece_hand": <string-or-null>
}

The items in a PMN array must be applied in the order they appear. This guarantees that composite moves—such as castling, en‑passant captures, or multi‑piece fairy moves—can be expressed unambiguously.

Square Labels

Piece Identifiers


Semantics & Consequences

The meaning of each field is intentionally simple yet powerful:

Field Semantics
src_square Where the piece comes from. null means “from hand / outside the board.”
dst_square Where the piece ends up. Always required.
piece_name What now sits on dst_square. It describes the post‑action state of that piece. Promotion, demotion, modifier changes, etc. must be reflected here.
piece_hand What (if anything) enters the mover’s reserve as a result of this action, or null if nothing enters the hand.

Given those definitions, every action item produces deterministic side‑effects:

  1. Board Removal – If src_square is not null, that square becomes empty.
  2. Board Placementdst_square contains piece_name after the action.
  3. Hand Addition – If piece_hand is not null, add such a piece to the mover’s reserve.
  4. Hand Removal – If src_square is null, remove a piece corresponding to piece_name from the mover’s reserve.

PMN does not verify that the mover actually had such a piece in reserve, or that any action is legal. Engines must enforce game rules on top of PMN.

These consequences are invariant: they apply to Chess, Shōgi, Xiangqi, Fairy variants, or any hybrid game, regardless of the piece notation system used.


JSON Schema

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Portable Move Notation (PMN) v1.0.0",
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "src_square": {
        "type": ["string", "null"],
        "minLength": 1
      },
      "dst_square": {
        "type": "string",
        "minLength": 1
      },
      "piece_name": {
        "type": "string",
        "minLength": 1
      },
      "piece_hand": {
        "type": ["string", "null"],
        "minLength": 1
      }
    },
    "required": ["dst_square", "piece_name"],
    "additionalProperties": false
  },
  "minItems": 1
}

The schema intentionally leaves both square‑label and piece‑identifier strings unconstrained (except for non‑empty requirement) so that any coordinate and piece notation conventions may be used.


Examples

Coordinates and piece notations below are illustrative only; any convention may be substituted.

Shōgi · Promotion (using traditional notation)

A pawn promotes upon reaching the enemy camp.

[{ "src_square": "27", "dst_square": "18", "piece_name": "+P", "piece_hand": null }]

Chess · Pawn Move (using descriptive notation)

[{ "src_square": "e2", "dst_square": "e4", "piece_name": "WhitePawn", "piece_hand": null }]

Shōgi · Capture → Piece in Hand (using single letters)

A bishop captures a promoted pawn. The captured piece enters the mover’s hand.

[{ "src_square": "36", "dst_square": "27", "piece_name": "B", "piece_hand": "P" }]

Drop from Hand (using numeric codes)

Dropping a piece from hand to the board.

[{ "src_square": null, "dst_square": "27", "piece_name": "42", "piece_hand": null }]

Chess · Kingside Castling (using standard notation)

[
  { "src_square": "e1", "dst_square": "g1", "piece_name": "K", "piece_hand": null },
  { "src_square": "h1", "dst_square": "f1", "piece_name": "R", "piece_hand": null }
]

Chess · En Passant (showing state changes)

White advances a pawn two squares; Black captures en passant.

// White move
[{ "src_square": "e2", "dst_square": "e4", "piece_name": "P_moved", "piece_hand": null }]

// Black en passant capture
[
  { "src_square": "d4", "dst_square": "e3", "piece_name": "p", "piece_hand": null },
  { "src_square": "e4", "dst_square": "e4", "piece_name": null, "piece_hand": "P" }
]

Note: This example uses "P_moved" to indicate a pawn that has moved (for en passant eligibility) and shows the captured pawn being removed from e4. The actual piece notation would depend on the system being used.

Custom Game Example (using full names)

[{ "src_square": "center", "dst_square": "edge_7", "piece_name": "MagicDragon_powered", "piece_hand": null }]

Implementation Considerations

Piece Notation Systems

Since PMN is agnostic to piece notation, implementers should:

Common Notation Systems

While PMN supports any notation, some established systems include:

Backward Compatibility

Existing PMN implementations using PNN notation will continue to work without modification, as PNN-formatted strings are valid under the relaxed constraints.


Implementations

Ruby