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 局面解析)

rsshogi.usi は USI(Universal Shogi Interface)プロトコルの文字列と構造化オブジェクトを相互変換するステートレスなモジュールである。 また、rsshogi.core には USI の position コマンド文字列を検証、分解、正規化する関数群が用意されている。

from rsshogi.core import (
    UsiPositionParts,
    normalize_usi_position,
    parse_usi_position,
    parse_usi_position_parts,
)
from rsshogi.usi import (
    MAX_PLY,
    VALUE_MATE,
    VALUE_MATE_IN_MAX_PLY,
    UsiBestMove,
    UsiBound,
    UsiGoCommand,
    UsiInfo,
    UsiScore,
    move_from_usi,
    parse_bestmove,
    parse_info,
    parse_score,
)

定数と指し手変換(rsshogi.usi)

定数 / 関数型 / 値説明
MAX_PLYint(246)詰みスコア計算の基準となる最大探索手数。
VALUE_MATEint(32000)0 手詰みに対する内部スコア基準値。
VALUE_MATE_IN_MAX_PLYint(31754)VALUE_MATE - MAX_PLY(詰みスコアと判定する閾値)。
move_from_usi(usi)(usi: str) -> MoveUSI 指し手文字列を Move へ変換する。通常手と "0000" に加えて、"resign"(Move.WIN ではなく Move.RESIGN)、"win"(Move.WIN)、"none"(Move.NONE)も受理する。
parse_score(text)(text: str) -> UsiScore"cp 120" や "mate +5" などの USI スコア文字列を解析する。
parse_info(line)(line: str) -> UsiInfoUSI エンジンの info ... 出力行を解析する。
parse_bestmove(line)(line: str) -> UsiBestMoveUSI エンジンの bestmove ... 出力行を解析する。

Note

rsshogi.core.Move.from_usi(usi) は通常の指し手と "0000"(パス手)のみを受理し、"resign" や "win" には ValueError を送出する。エンジンの bestmove トークンを扱う場合は rsshogi.usi.move_from_usi(usi) または parse_bestmove(line) を使用する。


スコアと探索情報の解析(UsiScore / UsiBound / UsiInfo)

UsiBound

探索評価値が真の値のどの境界であるかを表す列挙型(IntEnum)である。

定数値 (value)to_usi() の戻り値説明
UsiBound.NONE0""境界指定なし。
UsiBound.UPPER1"upperbound"上界(実際の評価値はこの値以下)。
UsiBound.LOWER2"lowerbound"下界(実際の評価値はこの値以上)。
UsiBound.EXACT3""正確な評価値。

UsiScore

USI の score cp <x> および score mate <y> を表すイミュータブルなデータクラスである。

メソッド / プロパティシグネチャ / 型説明
UsiScore.cp(value)(value: int) -> UsiScoreセンチポーン評価値(kind="cp")を生成する(クラスメソッド)。
UsiScore.mate(plies)(plies: int) -> UsiScore手数付きの詰みスコア(kind="mate")を生成する(クラスメソッド)。
UsiScore.mate_plus()() -> UsiScore手数不明の詰み(score mate +、kind="mate_plus")を生成する(クラスメソッド)。
UsiScore.mate_minus()() -> UsiScore手数不明の被詰(score mate -、kind="mate_minus")を生成する(クラスメソッド)。
UsiScore.parse(text)(text: str) -> UsiScore"cp 85"、"score mate -3"、"mate +" などの文字列から UsiScore を生成する(クラスメソッド)。
UsiScore.from_raw(raw_score)(raw_score: int) -> UsiScore内部整数スコアから UsiScore へ変換する。絶対値が VALUE_MATE_IN_MAX_PLY(31754)以上の場合は詰みスコア(VALUE_MATE - abs(raw_score) 手詰み)に変換される(クラスメソッド)。
kindstr"cp"、"mate"、"mate_plus"、"mate_minus" のいずれか。
valueint | None"cp" または "mate" の場合の整数値("mate_plus" / "mate_minus" では None)。
to_usi_tokens()tuple[str, str]("cp", "85") や ("mate", "+") の 2 要素タプルを返す。
to_usi() / str(score)str"cp 85" や "mate -3" 形式の文字列を返す。
to_raw()intVALUE_MATE(32000)基準の内部整数スコアへ変換する。

UsiInfo

UsiInfo.parse(text: str) -> UsiInfo
parse_info(line: str) -> UsiInfo

USI エンジンが出力する info 行の各項目を保持するイミュータブルなデータクラスである。 score トークンが含まれる場合、score プロパティには to_raw() で変換された内部整数スコアが入り、raw_score プロパティには UsiScore オブジェクトが入る。

プロパティ型説明
depthint | None基本探索深さ(depth)。
seldepthint | None選択探索深さ(seldepth)。
timeint | None探索経過時間(ミリ秒、time)。
nodesint | None探索ノード数(nodes)。
npsint | None1 秒あたりの探索ノード数(nps)。
hashfullint | None置換表の使用率(千分率、hashfull)。
multipvint | NoneMultiPV の順位番号(multipv)。
scoreint | None内部整数表現の評価値(raw_score.to_raw())。
raw_scoreUsiScore | None構造化された評価値オブジェクト。
boundUsiBoundlowerbound / upperbound の区分(指定がない場合は UsiBound.NONE)。
pvtuple[Move, ...]読み筋(Principal Variation)の指し手タプル。
textstr | Noneinfo string ... の文字列メッセージ。
from rsshogi.usi import UsiBound, parse_info

info = parse_info(
    "info depth 18 seldepth 26 time 450 nodes 890000 nps 1977777 hashfull 310 "
    "multipv 1 score cp 145 lowerbound pv 7g7f 3c3d 2g2f"
)
assert info.depth == 18
assert info.score == 145
assert info.raw_score is not None and info.raw_score.to_usi() == "cp 145"
assert info.bound is UsiBound.LOWER
assert [m.to_usi() for m in info.pv] == ["7g7f", "3c3d", "2g2f"]

UsiBestMove と UsiGoCommand

UsiBestMove

UsiBestMove(bestmove: Move, ponder: Move | None = None) -> UsiBestMove
UsiBestMove.parse(text: str) -> UsiBestMove
parse_bestmove(line: str) -> UsiBestMove

エンジンの bestmove 応答行を表すイミュータブルなデータクラスである。

プロパティ / メソッド型説明
bestmoveMove最善手(投了時は Move.RESIGN、入玉宣言時は Move.WIN)。
ponderMove | None予想応手(指定がない場合は None)。
to_string() / str(bm)str"bestmove 7g7f ponder 3c3d" 形式の USI 文字列を返す。

UsiGoCommand

UsiGoCommand(
    *,
    searchmoves: tuple[Move, ...] = (),
    ponder: bool = False,
    btime: int | None = None,
    wtime: int | None = None,
    byoyomi: int | None = None,
    binc: int | None = None,
    winc: int | None = None,
    nodes: int | None = None,
    depth: int | None = None,
    mate: int | None = None,
    infinite: bool = False,
) -> UsiGoCommand

エンジンへ送信する go コマンドを組み立てるイミュータブルなデータクラスである。 mate に負の整数(例:-1)を指定すると go mate infinite として出力され、正の整数を指定すると詰み探索の制限時間(ミリ秒)として出力される。

メソッド戻り値説明
to_string() / str(cmd)str設定されたフィールドから "go ..." コマンド文字列を生成する。
from rsshogi.core import Move
from rsshogi.usi import UsiGoCommand, parse_bestmove

cmd = UsiGoCommand(
    searchmoves=(Move.from_usi("7g7f"), Move.from_usi("2g2f")),
    btime=60000,
    wtime=60000,
    byoyomi=10000,
    depth=20,
)
print(cmd.to_string())
# => "go searchmoves 7g7f 2g2f btime 60000 wtime 60000 byoyomi 10000 depth 20"

bm = parse_bestmove("bestmove 7g7f ponder 3c3d")
print(bm.bestmove.to_usi(), bm.ponder.to_usi() if bm.ponder else None)
# => 7g7f 3c3d

USI position 文字列の解析と正規化(rsshogi.core)

USI の position コマンド文字列("position startpos moves 7g7f 3c3d" や "sfen ... moves ...")を検証し、初期局面、合法手リスト、最終局面に分解する関数群が rsshogi.core に用意されている。 手順中に非合法手や不正なトークンが含まれている場合は ValueError を送出する。

関数 / クラスシグネチャ説明
parse_usi_position(position)(position: str) -> tuple[str, list[Move]]USI position 文字列を解析し、(初期局面の SFEN, 合法手の Move リスト) のタプルを返す。
parse_usi_position_parts(position)(position: str) -> UsiPositionPartsUSI position 文字列を解析し、初期局面、手順、最終局面をまとめた UsiPositionParts を返す。
normalize_usi_position(position)(position: str) -> strUSI position 文字列を検証したうえで、正規化された "position startpos ..." または "position sfen ..." 文字列へ変換する。

UsiPositionParts

parse_usi_position_parts(position) が返すオブジェクトは以下のプロパティとメソッドを持つ。

プロパティ / メソッド型説明
initial_sfenstr開始局面の正規化された SFEN 文字列。
moveslist[Move]合法性を検証済みの 16 ビット Move のリスト。
move_usilist[str]各指し手の USI 文字列のリスト。
final_sfenstrすべての指し手を適用した後の最終局面の SFEN 文字列。
to_dict()dict[str, Any]initial_sfen、moves、move_usi、final_sfen の 4 キーを持つ辞書を返す。
from rsshogi.core import normalize_usi_position, parse_usi_position_parts

parts = parse_usi_position_parts("startpos moves 7g7f 3c3d")
print(parts.initial_sfen)
# => "lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1"
print(parts.move_usi)
# => ['7g7f', '3c3d']
print(parts.final_sfen)
# => "lnsgkgsnl/1r5b1/pppppp1pp/6p2/9/2P6/PP1PPPPPP/1B5R1/LNSGKGSNL b - 3"

normalized = normalize_usi_position("startpos moves 7g7f")
assert normalized == "position startpos moves 7g7f"

Board および Record との連携

関連項目