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
- A square label is an arbitrary non‑empty UTF‑8 string agreed upon by all actors of a game session.
- Labels can be purely numeric (e.g.
"42"
), purely alphabetic (e.g."c"
), alphanumeric (e.g."c3"
), or use any other convention (e.g."@4,7"
). - PMN never interprets the content of the label; it only requires that identical strings refer to the same board location during a session.
Piece Identifiers
- A piece identifier is an arbitrary non‑empty UTF‑8 string representing a game piece.
- PMN imposes no constraints on the format or content of piece identifiers.
- The interpretation and validation of piece identifiers is left entirely to the implementing system.
- Identifiers can follow any convention: single letters (
"K"
,"p"
), full names ("WhiteKing"
,"blackPawn"
), numeric codes ("1"
,"42"
), or any other format.
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:
- Board Removal – If
src_square
is notnull
, that square becomes empty. - Board Placement –
dst_square
containspiece_name
after the action. - Hand Addition – If
piece_hand
is notnull
, add such a piece to the mover’s reserve. - Hand Removal – If
src_square
isnull
, remove a piece corresponding topiece_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 }]
- Before: square
"27"
contained some piece. - After: square
"27"
is empty; square"18"
contains"+P"
.
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:
- Document their conventions: Clearly specify which piece notation system is used
- Maintain consistency: Use the same notation system throughout a game session
- Handle conversions: If interfacing with other systems, provide conversion utilities
- Validate appropriately: Apply piece notation validation at the application level, not PMN level
Common Notation Systems
While PMN supports any notation, some established systems include:
- Single letters:
K
,Q
,R
,B
,N
,P
(Chess traditional) - Descriptive names:
"WhiteKing"
,"BlackQueen"
(self-documenting) - PNN format:
+P
,R'
,-N
(with state modifiers) - GAN format:
CHESS:K
,shogi:+p
(game-qualified pieces) - Numeric codes:
1
,2
,3
(compact representation) - Unicode symbols:
♔
,♛
,♜
(visual representation)
Backward Compatibility
Existing PMN implementations using PNN notation will continue to work without modification, as PNN-formatted strings are valid under the relaxed constraints.
Related Specifications
- Piece Name Notation (PNN) — one possible piece identifier format.
- General Actor Notation (GAN) — game-qualified piece identifiers.
- Forsyth‑Edwards Enhanced Notation (FEEN) — static positions.
Implementations
Ruby
- Pmn.rb – Reference implementation.