Portable Chess Notation

A general purpose JSON-based format for recording chess variants.

Created
Updated
Version
1.0.0

Introduction

PCN (Portable Chess Notation) is a lightweight format based on JSON and PMN that gives a consistent and easy way to represent most chess games between two-players.

Able to describe both multidimensional games and related moves, in progress and finished games, easy for humans to read and write, and easy for machines to import and export, it is completely laws of chess independent and compatible with the main variants, including 장기Janggi, หมากรุกMakruk, 将棋Shogi, Chess, 象棋Xiangqi. These properties make PCN an ideal data-interchange format for recording chess games.

Notational conventions

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

How to serve PCN

The use of the file suffix “.pcn” is RECOMMENDED for files containing PCN data.

When serving PCN over HTTP, the media type “application/vnd.pcn+json” is RECOMMENDED.

Notation for Games

Resource representation

The JSON structure below shows the format of the resource:

{
  "bottomside": {a object representing the bottom-side player},
  "event": {a string},
  "finished_at": {a datetime},
  "href": {a string},
  "indexes": {an array},
  "location": {a string},
  "moves": {an array},
  "name": {a string},
  "round": {an unsigned integer},
  "setup": {a object representing the initialization parameters of the game},
  "started_on": {a date},
  "state": {a object representing the properties of the last position},
  "topside": {a object representing the top-side player}
}
Properties

The following table defines the properties that appear in this resource:

Property name Type Required Default Description
bottomside a player object false {} The bottom-side player.
event a string false null The name of the tournament or match event.
finished_at a datetime false null The datetime when the game could end or ended.
href a string false null A website that display the game.
indexes an array true   The shape of the board.
location a string false null The place or position of the game.
moves an array false [] The moves previously played.
name a string false null The name of the game.
round an unsigned integer false null The playing round ordinal of the game.
setup a setup object true   The initialization parameters of the game.
started_on a date false null The date the game started.
state a state object false {} The properties of the last position.
topside a player object false {} The top-side player.

Bottom-side player

The reserved “bottomside” property is RECOMMENDED.

The “bottomside” property represents the bottom-side player.

Event

The reserved “event” property is RECOMMENDED.

The “event” property is the name of the tournament or match event.

Finished datetime

The reserved “finished_at” property is RECOMMENDED.

The “finished_at” property specifies the datetime when the game could end or ended.

The value is specified in ISO 8601 format (eg “1994-11-05T13:15:30Z”).

If the property is not present, or if the property is present and its value is null or smaller than or equal to the current datetime, the game MUST be considered finished. Otherwise, the game MUST be considered in progress because the value is greater than the current datetime.

Hyperlink

The reserved “href” property is RECOMMENDED.

The “href” property specifies a link that targets a document about the game.

Indexes of the board

The reserved “indexes” property is REQUIRED.

The “indexes” property specifies the shape of the board.

This is a tuple of integers indicating the size of the array in each dimension. For a two-dimensional board, n would be the number of rows and m the number of columns: [n, m].

Examples:

Location

The reserved “location” property is RECOMMENDED.

Indicates the place or position that the game was in or where it happened.

Example: “San Francisco, CA

Moves

The reserved “moves” property is OPTIONAL.

The “moves” property represents an ordered set of actions based on Portable Move Notation format.

If the property is not present, or if the property is present and its value is null, the list of moves MUST be considered as empty.

King’s Gambit example:

[
  [52, 36, "P", nil],
  [12, 28, "p", nil],
  [53, 37, "P", nil]
]

Name

The reserved “name” property is RECOMMENDED.

Indicates the name of the game.

Round

The reserved “round” property is RECOMMENDED.

The “round” property is the number of the game played between two players.

If present, the value MUST be greater than or equal to 1.

Setup

The reserved “setup” property is REQUIRED.

The “setup” property represents the initialization parameters of the game.

Started date

The reserved “started_on” property is RECOMMENDED.

The “started_on” property specifies the starting date for the game.

The value is specified in ISO 8601 format (eg “1997-07-16”).

State

The reserved “state” property is RECOMMENDED.

The “state” property represents the properties of the last position.

Top-side player

The reserved “topside” property is RECOMMENDED.

The “topside” property represents the top-side player.


Setup object

Resource representation

The JSON structure below shows the format of the resource:

{
  "bottomside_in_hand_pieces": {an array},
  "is_topside_moves_first": {a boolean},
  "squares": {an array},
  "topside_in_hand_pieces": {an array}
}
Properties

The following table defines the properties that appear in this resource:

Property name Type Required Default Description
bottomside_in_hand_pieces an array false [] The list of bottom-side’s pieces in hand.
is_topside_moves_first a boolean false false The player who plays first.
squares an array true   The first position of the game.
topside_in_hand_pieces an array false [] The list of top-side’s pieces in hand.

Bottom-side's pieces in hand

The reserved “bottomside_in_hand_pieces” property is RECOMMENDED.

The “bottomside_in_hand_pieces” property represents a set of pieces retained in hand by bottom-side player at the starting position.

If the property is not present, or if the property is present and its value is null, the list of pieces in hand MUST be considered as empty.

The player who plays first

The reserved “is_topside_moves_first” property is RECOMMENDED.

If the property is not present, or if the property is present and its value is null, the value false MUST be applied by default (meaning bottom-side plays first).

When the list of moves is empty, indicates the player who MUST make the first one. Or when the list of moves is not empty, indicates the player who made the first one.

The first position of the game

The reserved “squares” property is REQUIRED.

The “squares” property specifies a one-dimensional list of squares representing the first position. It could represent a starting position, or the position of a Chess problem.

Chess starting position example:

[
  "♜", "♞", "♝", "♛", "♚", "♝", "♞", "♜",
  "♟", "♟", "♟", "♟", "♟", "♟", "♟", "♟",
  null, null, null, null, null, null, null, null,
  null, null, null, null, null, null, null, null,
  null, null, null, null, null, null, null, null,
  null, null, null, null, null, null, null, null,
  "♙", "♙", "♙", "♙", "♙", "♙", "♙", "♙",
  "♖", "♘", "♗", "♕", "♔", "♗", "♘", "♖"
]

Janggi starting position example:

[
  "r", "m", "e", "s", null, "s", "e", "m", "r",
  null, null, null, null, "g", null, null, null, null,
  null, "p", null, null, null, null, null, "p", null,
  "j", null, "j", null, "j", null, "j", null, "j",
  null, null, null, null, null, null, null, null, null,
  null, null, null, null, null, null, null, null, null,
  "J", null, "J", null, "J", null, "J", null, "J",
  null, "P", null, null, null, null, null, "P", null,
  null, null, null, null, "G", null, null, null, null,
  "R", "M", "E", "S", null, "S", "E", "M", "R"
]

Makruk starting position example:

[
  "r", "n", "b", "q", "k", "b", "n", "r",
  null, null, null, null, null, null, null, null,
  "p", "p", "p", "p", "p", "p", "p", "p",
  null, null, null, null, null, null, null, null,
  null, null, null, null, null, null, null, null,
  "P", "P", "P", "P", "P", "P", "P", "P",
  null, null, null, null, null, null, null, null,
  "R", "N", "B", "K", "Q", "B", "N", "R"
]

Shogi starting position example:

[
  "l", "n", "s", "g", "k", "g", "s", "n", "l",
  null, "r", null, null, null, null, null, "b", null,
  "p", "p", "p", "p", "p", "p", "p", "p", "p",
  null, null, null, null, null, null, null, null, null,
  null, null, null, null, null, null, null, null, null,
  null, null, null, null, null, null, null, null, null,
  "P", "P", "P", "P", "P", "P", "P", "P", "P",
  null, "B", null, null, null, null, null, "R", null,
  "L", "N", "S", "G", "K", "G", "S", "N", "L"
]

Shogi tsume position example:

[
  null, null, null, "s", "k", "s", null, null, null,
  null, null, null, null, null, null, null, null, null,
  null, null, null, null, "+P", null, null, null, null,
  null, null, null, null, null, null, null, null, null,
  null, null, null, null, null, null, null, "+B", null,
  null, null, null, null, null, null, null, null, null,
  null, null, null, null, null, null, null, null, null,
  null, null, null, null, null, null, null, null, null,
  null, null, null, null, null, null, null, null, null
]

Xiangqi starting position example:

[
  "車", "馬", "象", "士", "將", "士", "象", "馬", "車",
  null, null, null, null, null, null, null, null, null,
  null, "砲", null, null, null, null, null, "砲", null,
  "卒", null, "卒", null, "卒", null, "卒", null, "卒",
  null, null, null, null, null, null, null, null, null,
  null, null, null, null, null, null, null, null, null,
  "兵", null, "兵", null, "兵", null, "兵", null, "兵",
  null, "炮", null, null, null, null, null, "炮", null,
  null, null, null, null, null, null, null, null, null,
  "俥", "傌", "相", "仕", "帥", "仕", "相", "傌", "俥"
]

Top-side's pieces in hand

The reserved “topside_in_hand_pieces” property is RECOMMENDED.

The “topside_in_hand_pieces” property represents a set of pieces retained in hand by top-side player at the starting position.

If the property is not present, or if the property is present and its value is null, the list of pieces in hand MUST be considered as empty.

State object

Resource representation

The JSON structure below shows the format of the resource:

{
  "is_in_check": {a boolean},
  "is_topside_better": {a boolean}
}
Properties

The following table defines the properties that appear in this resource:

Property name Type Required Default Description
is_in_check a boolean false null The King is under threat of capture on their opponent’s next turn.
is_topside_better a boolean false null Depending on whether the game is in progress or over, may indicate whether the game is won, lost or drawn.

In check?

The reserved “is_in_check” property is RECOMMENDED.

The “is_in_check” property specifies the current player’s king (or general in Xiangqi and Janggi) is under threat of capture on their opponent’s next turn.

Top-side better?

The reserved “is_topside_better” property is RECOMMENDED.

When the game is in progress, indicates whether top-side would win, lose or if there would be a draw at the end of regulation time. Or when the game is over, indicates if top-side has won, lost or if there is a draw.

Player object

Resource representation

The JSON structure below shows the format of the resource:

{
  "elo": {an unsigned integer},
  "is_requesting_a_draw": {a boolean},
  "name": {a string}
}
Properties

The following table defines the properties that appear in this resource:

Property name Value Required Default Description
elo an unsigned integer false null The Elo rating of the player.
is_requesting_a_draw a boolean false false The player is offering a draw.
name a string false null The name of the player.

Player Elo

The reserved “elo” property is RECOMMENDED.

The “elo” property represents the relative skill level of a player at the beginning of the game, according to the Elo rating system.

If present, the value MUST be greater than or equal to 0.

Example: 1735

Draw request

The reserved “is_requesting_a_draw” property is RECOMMENDED.

The “is_requesting_a_draw” property represents a proposal for a draw from the player to the opponent player. If the opponent accepts, the game is a draw (by mutual agreement).

If the property is not present, or if the property is present and its value is null, there is no proposal for a draw.

Player's name

The reserved “name” property is RECOMMENDED.

The “name” property represents the name of the player.

Example: “Bob


Chess game example

The Immortal Game in PCN format:

{
  "bottomside": {
    "name": "Adolf Anderssen"
  },

  "event": "London",
  "finished_at": null,
  "href": "https://en.wikipedia.org/wiki/Immortal_Game",
  "indexes": [8, 8],
  "location": "London ENG",

  "moves": [
    [ 52, 36, "♙" ],
    [ 12, 28, "♟" ],
    [ 53, 37, "♙" ],
    [ 28, 37, "♟" ],
    [ 61, 34, "♗" ],
    [ 3, 39, "♛" ],
    [ 60, 61, "♔" ],
    [ 9, 25, "♟" ],
    [ 34, 25, "♗" ],
    [ 6, 21, "♞" ],
    [ 62, 45, "♘" ],
    [ 39, 23, "♛" ],
    [ 51, 43, "♙" ],
    [ 21, 31, "♞" ],
    [ 45, 39, "♘" ],
    [ 23, 30, "♛" ],
    [ 39, 29, "♘" ],
    [ 10, 18, "♟" ],
    [ 54, 38, "♙" ],
    [ 31, 21, "♞" ],
    [ 63, 62, "♖" ],
    [ 18, 25, "♟" ],
    [ 55, 39, "♙" ],
    [ 30, 22, "♛" ],
    [ 39, 31, "♙" ],
    [ 22, 30, "♛" ],
    [ 59, 45, "♕" ],
    [ 21, 6, "♞" ],
    [ 58, 37, "♗" ],
    [ 30, 21, "♛" ],
    [ 57, 42, "♘" ],
    [ 5, 26, "♝" ],
    [ 42, 27, "♘" ],
    [ 21, 49, "♛" ],
    [ 37, 19, "♗" ],
    [ 26, 62, "♝" ],
    [ 36, 28, "♙" ],
    [ 49, 56, "♛" ],
    [ 61, 52, "♔" ],
    [ 1, 16, "♞" ],
    [ 29, 14, "♘" ],
    [ 4, 3, "♚" ],
    [ 45, 21, "♕" ],
    [ 6, 21, "♞" ],
    [ 19, 12, "♗" ]
  ],

  "name": "Immortal Game",
  "round": null,

  "setup": {
    "bottomside_in_hand_pieces": [],
    "is_topside_moves_first": false,

    "squares": [
      "♜", "♞", "♝", "♛", "♚", "♝", "♞", "♜",
      "♟", "♟", "♟", "♟", "♟", "♟", "♟", "♟",
      null, null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null,
      "♙", "♙", "♙", "♙", "♙", "♙", "♙", "♙",
      "♖", "♘", "♗", "♕", "♔", "♗", "♘", "♖"
    ],

    "topside_in_hand_pieces": []
  },

  "started_on": "1851-06-21",

  "state": {
    "is_in_check": true,
    "is_topside_better": false
  },

  "topside": {
    "name": "Lionel Adalbert Bagration Felix Kieseritzky"
  }
}

Shogi game example

The shortest possible game in PCN format:

{
  "bottomside": null,
  "event": null,
  "finished_at": null,
  "href": "https://userpages.monmouth.com/~colonel/shortshogi.html",
  "indexes": [9, 9],
  "location": null,

  "moves": [
    [ 56, 47, "P" ],
    [ 3, 11, "g" ],
    [ 64, 24, "+B", "P" ],
    [ 5, 14, "g" ],
    [ 24, 14, "+B", "G" ],
    [ 4, 3, "k" ],
    [ null, 13, "G" ]
  ],

  "name": "The Shortest Possible Game of Shogi",
  "round": null,

  "setup": {
    "bottomside_in_hand_pieces": [],
    "is_topside_moves_first": false,

    "squares": [
      "l", "n", "s", "g", "k", "g", "s", "n", "l",
      null, "r", null, null, null, null, null, "b", null,
      "p", "p", "p", "p", "p", "p", "p", "p", "p",
      null, null, null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null, null,
      "P", "P", "P", "P", "P", "P", "P", "P", "P",
      null, "B", null, null, null, null, null, "R", null,
      "L", "N", "S", "G", "K", "G", "S", "N", "L"
    ],

    "topside_in_hand_pieces": []
  },

  "started_on": null,

  "state": {
    "is_in_check": true,
    "is_topside_better": false
  },

  "topside": null
}

Shogi tsume example

Classic tsume Shogi problem:

{
  "indexes": [9, 9],
  "moves": [
    [ 43, 13, "+B" ],
    [ 5, 13, "s", "b" ],
    [ null, 14, "S" ]
  ],

  "name": "Tsume in 2 moves",

  "setup": {
    "bottomside_in_hand_pieces": ["S"],
    "is_topside_moves_first": false,

    "squares": [
      null, null, null, "s", "k", "s", null, null, null,
      null, null, null, null, null, null, null, null, null,
      null, null, null, null, "+P", null, null, null, null,
      null, null, null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, "+B", null,
      null, null, null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null, null
    ],

    "topside_in_hand_pieces": []
  },

  "state": {
    "is_in_check": true,
    "is_topside_better": false
  }
}

Xiangqi game example

A very short game in PCN format:

{
  "bottomside": null,
  "event": null,
  "finished_at": null,
  "href": null,
  "indexes": [10, 9],
  "location": null,

  "moves": [
    [ 64, 67, "炮" ],
    [ 25, 22, "砲" ],
    [ 70, 52, "炮" ],
    [ 19, 55, "砲" ],
    [ 67, 31, "炮" ],
    [ 22, 58, "砲" ],
    [ 52, 49, "炮" ]
  ],

  "name": "Short Double Cannons Checkmate",
  "round": null,

  "setup": {
    "bottomside_in_hand_pieces": [],
    "is_topside_moves_first": false,

    "squares": [
      "車", "馬", "象", "士", "將", "士", "象", "馬", "車",
      null, null, null, null, null, null, null, null, null,
      null, "砲", null, null, null, null, null, "砲", null,
      "卒", null, "卒", null, "卒", null, "卒", null, "卒",
      null, null, null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null, null,
      "兵", null, "兵", null, "兵", null, "兵", null, "兵",
      null, "炮", null, null, null, null, null, "炮", null,
      null, null, null, null, null, null, null, null, null,
      "俥", "傌", "相", "仕", "帥", "仕", "相", "傌", "俥"
    ],

    "topside_in_hand_pieces": []
  },

  "started_on": null,

  "state": {
    "is_in_check": true,
    "is_topside_better": false
  },

  "topside": null
}

See also
Implementation
Informative References

This work is influenced by several documents.