Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

JKF フォーマット仕様

JKF(JSON Kifu Format)は、将棋の棋譜データを構造化された JSON オブジェクトとして表現するフォーマットである。 文字コードが UTF-8 に統一されており、Web アプリケーションやスクリプト言語から標準の JSON パーサだけで直接読み書きできる利点がある。

トップレベル構造

JKF のルートオブジェクトは、header、initial(省略可)、および moves の 3 つのプロパティで構成される。

{
  "header": {
    "先手": "先手太郎",
    "後手": "後手次郎",
    "棋戦": "テスト棋戦"
  },
  "initial": {
    "preset": "HIRATE"
  },
  "moves": [
    {
      "comments": ["初期局面コメント"]
    },
    {
      "move": {
        "color": 0,
        "from": { "x": 7, "y": 7 },
        "to": { "x": 7, "y": 6 },
        "piece": "FU"
      },
      "time": {
        "now": { "m": 0, "s": 3 },
        "total": { "m": 0, "s": 3 }
      }
    },
    {
      "move": {
        "color": 1,
        "from": { "x": 3, "y": 3 },
        "to": { "x": 3, "y": 4 },
        "piece": "FU"
      }
    },
    {
      "move": {
        "color": 0,
        "from": { "x": 8, "y": 8 },
        "to": { "x": 2, "y": 2 },
        "piece": "KA",
        "promote": true,
        "capture": "KA"
      }
    },
    {
      "special": "TORYO",
      "time": {
        "now": { "m": 0, "s": 5 }
      }
    }
  ]
}

1. header オブジェクト

対局メタデータを格納する文字列辞書である。 rsshogi は以下の日本語キーを RecordMetadata の標準フィールドと相互マッピングし、それ以外のキーをカスタム属性に格納する。

JKF header キーRecordMetadata の対応先
"先手"black_player
"後手"white_player
"棋戦"event
"場所"site
"開始日時"start_date
"終了日時"end_date
"持ち時間"time_control
"先手持ち時間"black_time_control
"後手持ち時間"white_time_control
"最大手数"max_moves
"持将棋"impasse_rule
"備考"comment

表に含まれないキー("戦型"、"手合割" など)は、RecordMetadata のカスタム属性(Rust の attributes()、Python の custom)に格納される。

2. initial オブジェクト(初期局面)

initial が省略された場合は平手初期局面("HIRATE")として扱われる。 rsshogi がサポートする preset 文字列は、定型局面 14 種類と任意局面を表す "OTHER" の計 15 種類である。

preset 値手合割preset 値手合割
"HIRATE"平手"3"三枚落ち
"KY"香落ち"4"四枚落ち
"KY_R"右香落ち"5"五枚落ち
"KA"角落ち"5_L"左五枚落ち
"HI"飛車落ち"6"六枚落ち
"HIKY"飛香落ち"8"八枚落ち
"2"二枚落ち"10"十枚落ち
"OTHER"任意局面(data 必須)

preset: "OTHER" と data.board のインデックス順序

"preset": "OTHER" を指定する場合は、同階層に "data" オブジェクト(color、board、hands)を記述する。

  • color:開始手番(0 が先手番、1 が後手番)。
  • board:9 要素 × 9 要素の 2 次元配列であり、外側の配列が筋(1 筋〜9 筋:x = file - 1)、内側の配列が段(一段〜九段:y = rank - 1) を表す(board[x][y])。すなわち board[0] は 1 筋(board[0][0] が 1 一、board[0][8] が 1 九)であり、board[8] は 9 筋(board[8][0] が 9 一、board[8][8] が 9 九)である。空きマスは空オブジェクト {} で表し、駒があるマスは {"color": 0, "kind": "FU"} のように記述する。
  • hands:要素数 2 の配列 [先手の持駒, 後手の持駒] で、各要素は {"FU": 0, "KY": 0, "KE": 0, "GI": 0, "KI": 2, "KA": 0, "HI": 0} の形式で枚数を指定する。
"initial": {
  "preset": "OTHER",
  "data": {
    "color": 0,
    "board": [
      [ { "color": 1, "kind": "OU" }, {}, {}, {}, {}, {}, {}, {}, {} ],
      [ { "color": 1, "kind": "FU" }, { "color": 1, "kind": "GI" }, {}, {}, {}, {}, {}, {}, {} ],
      [ {}, {}, {}, {}, {}, {}, {}, {}, {} ],
      [ {}, {}, {}, {}, {}, {}, {}, {}, {} ],
      [ {}, {}, {}, {}, {}, {}, {}, {}, {} ],
      [ {}, {}, {}, {}, {}, {}, {}, {}, {} ],
      [ {}, {}, {}, {}, {}, {}, {}, {}, {} ],
      [ {}, {}, {}, {}, {}, {}, {}, {}, {} ],
      [ {}, {}, {}, {}, {}, {}, {}, {}, {} ]
    ],
    "hands": [
      { "FU": 0, "KY": 0, "KE": 0, "GI": 0, "KI": 2, "KA": 0, "HI": 0 },
      { "FU": 17, "KY": 4, "KE": 4, "GI": 3, "KI": 2, "KA": 2, "HI": 2 }
    ]
  }
}

上記の例では、board[0][0](1 一)に後手の玉、board[1][0](2 一)に後手の歩、board[1][1](2 二)に後手の銀が配置されている。

3. moves 配列と指し手オブジェクト

moves 配列はインデックス 0 の要素が常に初期局面を表し、インデックス 1 以降が 1 手目、2 手目の指し手または終局特殊手を表す。 moves[0] には "move" を含めず、初期局面コメントがある場合にのみ "comments"(および先頭手からの分岐がある場合は "forks")を持たせる。

move オブジェクトのフィールド

フィールド型必須説明
color0 または 1○手番(0:先手、1:後手)。
from{"x": 1..9, "y": 1..9}盤上移動時移動元の筋 x と段 y。駒打ちの場合は from を省略(または null)する。
to{"x": 1..9, "y": 1..9}○移動先の筋 x と段 y。
piecestring○移動前の駒種コード(CSA 2 文字表記)。
sameboolean任意直前の指し手と同一の移動先(同)である場合に true。
promoteboolean任意移動時に成る場合は true、成れる移動で成らない(不成)場合は false。
capturestring任意移動先にあった捕獲対象の駒種コード(成駒を取った場合は "UM" などの成駒コード)。
relativestring任意同種駒が同じマスへ動ける場合の相対位置または動作修飾子("L", "C", "R", "U", "M", "D", "LU", "LM", "LD", "RU", "RM", "RD", "H")。

成り手における piece フィールドの注意点

CSA 形式の指し手文字列(+8822UM)とは異なり、JKF の move.piece には 成る前の駒種(移動元にある駒の種別) を指定する。 例えば、8 八の角を 2 二へ進めて馬に成る手では、"piece": "KA" かつ "promote": true と記述する("piece": "UM" は既に馬に成っている駒を動かす場合のみ使われる)。

{
  "move": {
    "color": 0,
    "from": { "x": 8, "y": 8 },
    "to": { "x": 2, "y": 2 },
    "piece": "KA",
    "promote": true,
    "capture": "KA"
  }
}

4. 消費時間(time)とコメント(comments)

各手オブジェクトには "time" と "comments" を付与できる。

  • time.now と time.total:それぞれ 1 手の消費時間と累計消費時間を {"h": 時間, "m": 分, "s": 秒} で表す。"h" は 0 時間の場合には省略される(1 時間以上のときのみ "h" が出力される)。
  • 終局特殊手における time:"special" を持つ終局特殊手エントリでは "time": {"now": ...} のみが出力され、"total" は出力されない。
  • comments:文字列の配列 ["1行目", "2行目"] として保持される。JKF には評価値専用フィールドがないため、rsshogi からのエクスポート時に EngineInfo.eval は出力されない。

持ち時間は KIF と同じ表記と base+byoyomi+increment を読み込む。 基本時間に秒端数がある場合は後者の表記で出力し、秒読みや加算と区別して保持する。

5. 終局特殊手(special)

終局を表すエントリは "move" の代わりに "special" フィールドを持つ。

JKF special 値SpecialMove勝敗結果(GameResult)
"TORYO"SpecialMove::Resign直前の指し手側の勝ち(BlackWin / WhiteWin)。
"CHUDAN"SpecialMove::InterruptGameResult::Paused
"SENNICHITE"SpecialMove::RepetitionDrawGameResult::DrawByRepetition
"TIME_UP"SpecialMove::Timeout直前の指し手側の時間切れ勝ち(BlackWinByTimeout / WhiteWinByTimeout)。
"ILLEGAL_MOVE"SpecialMove::WinByIllegalMove直前の指し手側の反則勝ち(BlackWinByIllegalMove / WhiteWinByIllegalMove)。
"+ILLEGAL_ACTION"SpecialMove::WinByIllegalMove先手の反則による GameResult::WhiteWinByIllegalMove。
"-ILLEGAL_ACTION"SpecialMove::WinByIllegalMove後手の反則による GameResult::BlackWinByIllegalMove。
"JISHOGI"SpecialMove::ImpasseGameResult::DrawByImpasse
"KACHI"SpecialMove::WinByDeclaration宣言した手番側の入玉宣言勝ち(BlackWinByDeclaration / WhiteWinByDeclaration)。
"HIKIWAKE"SpecialMove::DrawGameResult::DrawByImpasse
"TSUMI"SpecialMove::Mate直前の指し手側の勝ち(BlackWin / WhiteWin)。
"FUZUMI"SpecialMove::NoMateGameResult::Paused
"MAX_MOVES"SpecialMove::MaxMovesGameResult::DrawByMaxPlies
"ERROR"SpecialMove::InterruptGameResult::Error

符号付き ILLEGAL_ACTION は手番ではなく反則を犯した側を示す。 上記以外の文字列(例えば "MATTA")が指定された場合は、SpecialMove::Unknown および GameResult::Invalid として保持される。

出力時には、終局マーカーを読み戻した結果と記録済みの勝敗が一致することを検査する。 汎用の BlackWin / WhiteWin は勝者だけを照合し、終局理由は終局の種類から補う。 理由付きの結果は終局理由も一致する必要がある。 投了、詰み、時間切れは手番の相手を、入玉宣言は手番側を勝者とするため、異なる勝者は出力エラーになる。 元マーカーが残っていても記録済みの勝敗と矛盾する場合は拒否する。 不戦勝、不戦敗、トライは対応するマーカーがないため、別の終局理由へ置き換えず出力を拒否する。 本譜と変化の両方に同じ検査を適用する。

6. 分岐手順(forks)

ある手に対する別候補の分岐手順は、置き換え対象となる指し手の 1 つ前の要素(すなわち分岐元の親局面に対応する要素)の "forks" フィールドに格納される。 "forks" は「指し手オブジェクト配列」の配列(Vec<Vec<MoveFormat>>)であり、複数の変化手順および再帰的な入れ子分岐を表現できる。

  • 初手(1 手目)からの分岐:moves[0] の "forks" に格納される。
  • N 手目(N >= 2)からの分岐:moves[N - 1] の "forks" に格納される。

コード例

Python

import json
from rsshogi.record import Record

# JKF 文字列またはファイルからの読み込み
record = Record.from_jkf_str(jkf_text)
record_from_file = Record.from_jkf_file("sample.jkf")

# JKF 文字列へのエクスポートと JSON パース
jkf_out = record.to_jkf()
data = json.loads(jkf_out)

Rust

#![allow(unused)]
fn main() {
use rsshogi::records::formats::jkf::{export_jkf, parse_jkf_bytes, parse_jkf_str};

let record = parse_jkf_str(jkf_str)?;
let json_text = export_jkf(&record)?;
}

関連項目