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

USI プロトコル

rsshogi.usi は USI エンジンプロセスを起動・制御せず、USI プロトコルの 文字列を値オブジェクトへ変換するステートレスな補助 API です。

USI position の分解

parse_usi_position_parts() は USI position 文字列を、初期局面 SFEN・手順・ 最終局面 SFEN に分解します。

from rsshogi.core import parse_usi_position_parts

parts = parse_usi_position_parts("position startpos moves 7g7f 3c3d")
print(parts.initial_sfen)
print(parts.move_usi)    # ["7g7f", "3c3d"]
print(parts.final_sfen)

戻り値 UsiPositionParts は以下の属性を持ちます。

属性内容
initial_sfenstrstartpos または sfen ... が表す初期局面
moveslist[Move]合法性を確認して読み込まれた手順
move_usilist[str]moves を USI 文字列に戻したもの
final_sfenstr手順を適用した最終局面

USI position と Record

Record.from_usi_position() は USI position command を棋譜として読み込みます。 startpossfen ... の違いは保持されるため、to_usi_position() で同じ 開始局面 token に戻せます。

import rsshogi as rs

record = rs.record.Record.from_usi_position("position startpos moves 7g7f 3c3d")
assert record.to_usi_position() == "position startpos moves 7g7f 3c3d"

標準 USI では position ... moves に通常手だけを受け付けます。resign などの 非標準 token を終端特殊手として扱う場合は、明示的に extended mode を使います。

record = rs.record.Record.from_usi_position(
    "position startpos moves 7g7f resign",
    allow_special_tokens=True,
)
assert record.to_usi_position(include_special_tokens=True).endswith("resign")

info / bestmove の解析

UsiInfo.parse() / parse_info()info 行から depth, nodes, score, bound, PV などを取り出します。UsiBestMove.parse() / parse_bestmove()bestmove 行を読み込みます。

import rsshogi as rs

info = rs.usi.parse_info(
    "info depth 12 nodes 12345 score cp 37 lowerbound pv 7g7f 3c3d"
)
assert info.depth == 12
assert info.score == 37
assert info.bound is rs.usi.UsiBound.LOWER

best = rs.usi.parse_bestmove("bestmove 7g7f ponder 3c3d")
assert best.bestmove.to_usi() == "7g7f"

move_from_usi()resign, win, 0000, noneMove 定数へ変換します。 通常手だけを受け付ける Move.from_usi() と使い分けてください。

go コマンドの組み立て

UsiGoCommandgo コマンド文字列を組み立てる値オブジェクトです。

import rsshogi as rs

cmd = rs.usi.UsiGoCommand(
    searchmoves=(rs.core.Move.from_usi("7g7f"),),
    btime=1000,
    wtime=1000,
    byoyomi=500,
    depth=10,
)
print(cmd.to_string())
# go searchmoves 7g7f btime 1000 wtime 1000 byoyomi 500 depth 10

Record ヘルパー

Record.from_usi_main_line() は初期局面、USI 手順、任意のテレメトリ、 終局結果から合法手を適用しながら Record を作ります。

シグネチャ(すべてキーワードで渡せます):

Record.from_usi_main_line(
    init_position_sfen: str,
    usi_moves: list[str],
    result=None,
    move_times_ms: list[int | None] | None = None,
    evals: list[int | None] | None = None,
    nodes: list[int | None] | None = None,
    depths: list[int | None] | None = None,
    seldepths: list[int | None] | None = None,
    wall_times_ms: list[int | None] | None = None,
    latency_deltas_ms: list[int | None] | None = None,
    metadata=None,
    initial_comment: str | None = None,
) -> Record
import rsshogi as rs

record = rs.record.Record.from_usi_main_line(
    "startpos",
    ["7g7f", "3c3d"],
    result=rs.record.GameResult.WHITE_WIN,
    evals=[12, -8],
    nodes=[1000, 2000],
)

終局結果だけから標準の終局特殊手を作る場合は SpecialMoveEntry.from_result() を使います。

terminal = rs.record.SpecialMoveEntry.from_result(
    rs.record.GameResult.BLACK_WIN_BY_TIMEOUT,
    time_ms=3000,
)
assert terminal.kind == "TIMEOUT"

Board ヘルパー

Board.push_usi_with_delta() は合法手を適用し、差分 DTO を dict で返します。 Board.evaluate_declaration() は宣言勝ち判定の詳細条件を返します。 Board.solve_mate_in_one() は Rust core の 1 手詰めソルバを呼び出します。

from rsshogi.core import Board

board = Board()
delta = board.push_usi_with_delta("7g7f")
assert delta["kind"] == "BOARD"

declaration = board.evaluate_declaration()
print(declaration["can_declare"])

mate = board.solve_mate_in_one()

関連項目