Portable Chess Notation

A general purpose JSON-based format for recording cross-board and cross-style chess variants.

Created
Updated
Status
Draft
Author
Cyril Wack (contact @ cyril.io)

Diagram

Chess positions on the chessboard can be represented by an array.

Even though it is unusual, it is possible to represent a chessboard from one dimension. Each dimension can be described by an embedded array (where the first dimension should be the root array).

Some empty chessboard examples:

6 size (1 dimension)
[null, null, null, null, null, null]
7x7 size (2 dimensions)
[
  [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]
]

Example of use: Tori Shōgi (禽将棋)

4x8 size (2 dimensions)
[
  [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]
]

Example of use: Banqi (盲棋)

6x2x4 size (3 dimensions)
[
  [
    [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]
  ]
]

Piece notation naming

Each piece is identified by a string. Its regular expression can be:

/^[+]?[a-z0-9_]+:[a-z0-9_]+$/i

State

Promoted

Promoted pieces are prefixed by a + character, e.g. +s:b for a Shōgi promoted bishop.

Style

In order to distinguish the style of pieces, they are prefixed by a string. This string can contain letters, numbers and/or underscores. A piece's style regular expression can be: /^[a-z0-9_]+$/i.

For the main chess variants, the following letter abbreviations are used:

Janggi style
j
Makruk style
m
Shōgi style
s
Western style
w
Xiangqi style
x

For more exotic styles, it is recommended to use the full name to avoid possible collisions. Here is a non-exhaustive list:

Dai dai Shōgi style
dai_dai_shogi
Modern chess style
modern_chess
Shatranj style
shatranj
Shatar style
shatar
Taikyoku Shōgi style
taikyoku_shogi
Taihō Shōgi style
cannon_shogi
Wa Shōgi style
wa_shogi
Okisaki Shōgi style
okisaki_shogi

Abbreviation

After the piece's style, a : char is used as a separator, followed by an abbreviation given in algebraic notation. This abbreviation can contain letters, numbers and/or underscores. A regular expression for piece's abbreviation can be: /^[a-z0-9_]+$/i.

For the main chess variants, the following letter abbreviations are used:

Janggi pieces
  • j:g (General, called for Green and for Red)
  • j:a (Guard, called )
  • j:e (Elephant, called )
  • j:r (Chariot, called )
  • j:c (Cannon, called )
  • j:h (Horse, called )
  • j:s (Soldier, called for Green and for Red)
Makruk pieces
  • m:k (King, called ขุน)
  • m:q (Queen, called เม็ด)
  • m:r (Rook, called เรือ)
  • m:b (Bishop, called โคน)
  • m:n (Knight, called ม้า)
  • m:p (Pawn, called เบี้ย)
Shōgi pieces
  • s:k (King, called for Sente and for Gote)
  • s:g (Gold, called )
  • s:s (Silver, called )
  • s:r (Rook, called )
  • s:b (Bishop, called )
  • s:n (Knight, called )
  • s:l (Lance, called )
  • s:p (Pawn, called )
Western pieces
  • w:k (King)
  • w:q (Queen)
  • w:r (Rook)
  • w:b (Bishop)
  • w:n (Knight)
  • w:p (Pawn)
Xiangqi pieces
  • x:g (General, called for Black and for Red)
  • x:a (Advisor, called for Black and for Red)
  • x:e (Elephant, called for Black and for Red)
  • x:r (Chariot, called for Black and for Red)
  • x:c (Cannon, called for Black and for Red)
  • x:h (Horse, called for Black and for Red)
  • x:s (Soldier, called for Black and for Red)

Side

Pieces' side can be identified thanks to the case sensitivity of the abbreviation; that is, based on differing use of uppercase and lowercase letters. The pieces of the player who start the game are all uppercase (style and name in algebric notation), while the pieces of his opponent are all lowercase. Examples:

Topside player's pieces
  • w:p (Black Western's pawn)
  • taikyoku_shogi:gd (Gote Taikyoku Shōgi's Great Dragon)
Bottomside player's pieces
  • W:P (White Western's pawn)
  • TAIKYOKU_SHOGI:GD (Sente Taikyoku Shōgi's Great Dragon)

Shōgi info: player's captured pieces have to change the case of their abbreviation.

Coordinates Naming squares on the board

Each square of the chessboard can be identified by a Cartesian coordinate, a flatten coordinate, and—sometimes—a piece naming.

Cartesian coordinate

Cartesian coordinates are given via an array, according to the size of the board.

2D coordinates (with arrays)

Flatten coordinate

Flatten coordinates are given via an integer, according to the size of the flatten board.

Flatten coordinates (with integers)

Piece's coordinate

When there is a piece on a square, and if this piece's notation is unique on the board, then its notation can be used to identify a square, via a string.

Examples

Considering the initial position of Western games:
[
  ["w:r","w:n","w:b","w:q","w:k","w:b","w:n","w:r"],
  ["w:p","w:p","w:p","w:p","w:p","w:p","w:p","w: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, null, null, null, null, null],
  ["W:P","W:P","W:P","W:P","W:P","W:P","W:P","W:P"],
  ["W:R","W:N","W:B","W:Q","W:K","W:B","W:N","W:R"]
]

The Black Western King's coordinates can be identified by: [0,4], 4 or w:k.

Considering the following exotic board:
["w:k", "w:p", null,  "X:S", null, "X:G"]

The Xiangqi General's coordinates can be identified by: [5], 5 or X:G.

Considering this initial position with a Xiangqi player (north) against a Shōgi player (south) on a 9x9 board:
[
  ["x:r", "x:h", "x:e", "x:a", "x:g", "x:a", "x:e", "x:h", "x:r"],
  [ null,  null,  null,  null,  null,  null,  null,  null,  null],
  [ null, "x:c",  null,  null,  null,  null,  null, "x:c",  null],
  ["x:s",  null, "x:s",  null, "x:s",  null, "x:s",  null, "x:s"],
  [ null,  null,  null,  null,  null,  null,  null,  null,  null],
  [ null,  null,  null,  null,  null,  null,  null,  null,  null],
  ["S:P", "S:P", "S:P", "S:P", "S:P", "S:P", "S:P", "S:P", "S:P"],
  [ null, "S:B",  null,  null,  null,  null,  null, "S:R",  null],
  ["S:L", "S:N", "S:S", "S:G", "S:K", "S:G", "S:S", "S:N", "S:L"]
]

The first Xiangqi Chariot's coordinates can be identified by: [0,0] or 0.

Considering the following 3D game (6x2x4 size):
[
  [
    [ null, null, null, null],
    [ null, null,"w:k", null]
  ],
  [
    ["w:p","w:p","w:p","w:p"],
    [ null, null,"w:p", null]
  ],
  [
    [ null, null, null, null],
    [ null, null,"w:p", null]
  ],
  [
    ["w:p","w:P", null, null],
    ["S:P", null, null,"S:P"]
  ],
  [
    [ null,"S:P", null, null],
    ["S:P","S:P","S:P","S:P"]
  ],
  [
    [ null, null, null,"S:K"],
    [ null, null, null, null]
  ]
]
  • The Western King's coordinates can be identified by: [0,1,2], 6 or w:k.
  • The Shōgi King's coordinates can be identified by: [5,0,3], 43 or S:K.

A move is a list of actions.

Action

Each action is an array of 4 elements given in the present order:

  1. subject
  2. verb
  3. object
  4. options

Subject

The subject of an action is a piece, most of the case owned by the current player. When a given piece is unique on the board or when a piece is retained in hand (Shōgi style), it can be identified by its name. For instance a Western's White King could be namely identified by W:K. It is also possible to identify a piece from its square coordinates, for instance [5, 8] on a two-dimensional board, or from its square id (regardless of the number of dimensions of the board), for instance 42.

Verb

There are several verbs which we can use by action.

Drop

The drop action allows to put a piece on a free square of the board. This action is useful for Shōgi's captured pieces which are retained in hand. Or even for Go's stones.

Examples
Let a Shōgi's Sente lance which is dropped to the 23th square:
["S:L", "drop", [2, 4]]
Let a Shōgi's Gote pawn which was captured by Sente, and then captured again by Gote who is dropping it to the square number 42:
["s:p", "drop", 42]
Let a game with a Shōgi player who is dropping to the 10th square its captured Western queen:
["w:q", "drop", 10]

Capture

The capture action allows to move a piece from the board to a square occupied by an opponent's piece, which is captured from play.

Shōgi info: captured pieces are said to be in hand at Shōgi.

Remove

The remove action allows to move a piece from the board to a square occupied by an opponent's piece, which is removed from play.

Shift

The shift action allows to move a piece from the board to an unoccupied square.

Example
Let a Western chess game where the White Queen is moving to the square number 34:
["W:Q", "shift", [4, 2]]

Jump

The jump action allows to move an owned piece from a square to another square above.

Land

The land action allows to move an owned piece from a square above to another square.

Stun

The stun action allows to move an owned piece from a square above to another square, taking an opponent's piece.

Object

An object can be a piece or a square. If it is a piece, it can be identified just like a subject (with its name, its square coordinates or its square id). If it is a square, it can be identified by its coordinates or by its id.

Options

Given through a collection of key-value pairs, some special options allow to perform particular operations.

Promotion

When given, the value of the promotion key must be the piece naming of the promoted piece, while the promotable piece is the subject of the action. Promotions take effect after the completion of their action.

For instance, assuming the board is 8x8 size, it could describe the transformation of a Western pawn that reaches its eighth rank into the player's choice of a queen, knight, rook, or bishop. Let's promote a Black's pawn into a knight (using the option {"promotion": "w:n"}):

[ 51, "shift", 59, {"promotion": "w:n"} ]

Another example with a Shōgi player, where a promotable s:r piece could be promoted with the option {"promotion": "+s:r"}, capturing from the promotion zone a piece:

[ "s:r", "capture", [7, 1], {"promotion": "+s:r"} ]

Status

Over Result Description
false false draw proposal from top
false true draw proposal from bottom
false null game in progress
true false top is the winner
true true bottom is the winner
true null it's a draw

Example

Bottom is the winner:

{
  "over?": true,
  "...result?": true
}

Example

Here is a sample game in PCN format:

{
  "started_at": "2012-09-29T18:48:40+02:00",
  "topside_player": "Alice",
  "bottomside_player": "Bob",
  "over?": true,
  "...result?": true,
  "starting_position": [
    ["x:r", "x:h", "x:e", "x:a", "x:g", "x:a", "x:e", "x:h", "x:r"],
    [ null,  null,  null,  null,  null,  null,  null,  null,  null],
    [ null, "x:c",  null,  null,  null,  null,  null, "x:c",  null],
    ["x:s",  null, "x:s",  null, "x:s",  null, "x:s",  null, "x:s"],
    [ null,  null,  null,  null,  null,  null,  null,  null,  null],
    [ null,  null,  null,  null,  null,  null,  null,  null,  null],
    ["S:P", "S:P", "S:P", "S:P", "S:P", "S:P", "S:P", "S:P", "S:P"],
    [ null, "S:B",  null,  null,  null,  null,  null, "S:R",  null],
    ["S:L", "S:N", "S:S", "S:G", "S:K", "S:G", "S:S", "S:N", "S:L"]
  ],
  "previous_moves": [
    [[[8, 3], "shift", [7, 3]]],
    [[[3, 4], "shift", [3, 3]]],
    [[[8, 5], "shift", [7, 6]]],
    [[[0, 5], "shift", [1, 4]]],
    [[[6, 0], "shift", [5, 0]]],
    [[[2, 7], "shift", [2, 6]], [[2, 6], "shift", [2, 5]], [[2, 5], "shift", [2, 4]]],
    [[[8, 4], "shift", [8, 5]]],
    [[[3, 6], "shift", [3, 5]]],
    [[[6, 8], "shift", [5, 8]]],
    [[[3, 8], "shift", [3, 7]]],
    [[[8, 0], "shift", [7, 0]]],
    [[[1, 4], "shift", [2, 5]]],
    [[[6, 5], "shift", [5, 5]]],
    [[[0, 6], "shift", [1, 7]], [[1, 7], "shift", [2, 8]]],
    [[[7, 1], "shift", [6, 0]]],
    [[[3, 5], "shift", [4, 5]]],
    [[[8, 6], "shift", [7, 5]]],
    [[[2, 4], "shift", [2, 3]], [[2, 3], "shift", [2, 2]]],
    [[[5, 5], "capture", [4, 5]]],
    [[[3, 2], "shift", [3, 1]]],
    [[[8, 8], "shift", [7, 8]], [[7, 8], "shift", [6, 8]]],
    [[[0, 3], "shift", [1, 2]]],
    [["x:S", "drop", 22]],
    [[[0, 4], "shift", [0, 3]]],
    [[[6, 1], "shift", [5, 1]]],
    [[[2, 2], "shift", [3, 2]], [[3, 2], "shift", [4, 2]], [[4, 2], "shift", [5, 2]], [[5, 2], "jump", [6, 2]], [[6, 2], "land", [7, 2]], [[7, 2], "capture", [8, 2]]],
    [[[8, 5], "shift", [8, 6]]],
    [[[2, 1], "shift", [2, 0]]],
    [[[7, 3], "shift", [7, 2]]],
    [[[2, 8], "shift", [1, 7]], [[1, 7], "shift", [0, 6]]],
    [[[7, 2], "capture", [8, 2]]],
    [[[3, 1], "shift", [4, 1]]],
    [["x:C", "drop", 5]],
    [[[4, 1], "remove", [5, 1]]],
    [[[6, 7], "shift", [5, 7]]],
    [[[2, 0], "shift", [2, 1]]],
    [[[8, 2], "shift", [8, 3]]],
    [[[3, 0], "shift", [4, 0]]],
    [[[6, 0], "shift", [7, 1]]],
    [[[0, 3], "shift", [1, 3]]],
    [[[8, 1], "shift", [6, 0]]],
    [[[0, 6], "shift", [1, 7]], [[1, 7], "shift", [2, 8]]],
    [[[8, 3], "shift", [7, 4]]],
    [[[1, 3], "shift", [0, 4]]],
    [[[5, 0], "capture", [4, 0]]],
    [[[2, 1], "shift", [2, 0]]],
    [["x:S", "drop", 75]],
    [[[0, 4], "shift", [1, 4]]],
    [[[2, 4], "capture", [1, 4]]]
  ],
  "...cache": {
    "current_position": [
      [ null,  null,  null,  null,  null,  null,  null,  null,  null],
      [ null, "x:c",  null,  null,  null,  null,  null, "x:c",  null],
      ["x:s",  null, "x:s",  null, "x:s",  null, "x:s",  null, "x:s"],
      [ null,  null,  null,  null,  null,  null,  null,  null,  null],
      [ "..." ]
    ],
    "possible_moves": [],
    "topside": {
      "dropable_pieces": [],
      "captures": [{"piece": "x:g", "from": "S:L"}]
    },
    "bottomside": {
      "dropable_pieces": [],
      "captures": []
    }
  }
}
This is a fictitious game with random moves. It is meant merely to show the format of a PCN game record.

The Portable Chess Notation (PCN) format is in the Public Domain.

The format for PCN is in the public domain and is thus free for use for any purpose, commercial or private.