BeamNG.Earth
BeamNG.drive용 1:1 비율 실시간 지구, 실제 고도·위성 이미지·부동 원점·보조 서버에서 LOD 스트리밍
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기USIプロトコル対応の最小構成将棋エンジン
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Hayanagi は、C++17 で実装した USI プロトコル対応の最小構成将棋エンジンです。
通常対局用の探索に加えて、詰将棋用の詰み探索(TsumeSearch)を備え、
将棋 GUI ShogiBoardQ に静的ライブラリとして組み込まれています。
id name は Hayanagi 1.5.1。./build/hayanagi --version でも表示できますhayanagi、組み込み用の静的ライブラリは hayanagi_tsumebench / perft をひととおり実装docs/index.html)Hayanagi で学ぶ将棋エンジンの仕組み は、ソースコードを題材にした全15章のHTML教材です。 C++の基本文法と将棋のルールを知っている方に向けて、データ表現、ビットボード、局面管理、合法手生成、 終局判定、探索と評価、並列化、定跡、USIプロトコルを図とコード例で解説しています。
教材と紹介ページは GitHub Pages で公開しています。
手元で読む場合は、リポジトリを取得して docs/textbook.html(紹介ページは docs/index.html)をブラウザーで開いてください。
HTML・CSS・図版を同梱しているため、ビルドやWebサーバーの起動は不要です。
教材内のコード例や行数には執筆時点の構成が含まれます。最新の実装は src/ を参照してください。
現在の静的評価処理は src/evaluation.cpp にあり、探索処理から分離しています。
__builtin_ctzll などの組み込み関数を使います)cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
生成物は次のとおりです。
| 生成物 | 内容 |
|---|---|
build/hayanagi | USI エンジン実行ファイル |
build/libhayanagi_tsume.a | Position と TsumeSearch の静的ライブラリ(GUI 組み込み用) |
build/libhayanagi_search.a | 通常探索と静的評価の静的ライブラリ(本体・単体テストで共有) |
build/hayanagi_tests | C++ 単体テスト(Hayanagi を最上位でビルドしたときだけ生成) |
build/hayanagi_book_positions | 定跡生成用の棋譜検査・SFEN変換(HAYANAGI_BUILD_BOOK_TOOLS で制御) |
build/hayanagi_match_referee | 定跡比較対局用の合法手・終局判定(同オプションで制御) |
コンパイル警告は -Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wno-sign-conversion を有効にしており、GCC と Clang のどちらでも警告なしでビルドできます(Clang の -Wconversion は -Wsign-conversion を含むため、GCC と同じ意味になるよう明示的に無効にしています)。
./build/hayanagi --version # Hayanagi 1.5.1
./build/hayanagi # USI エンジンとして起動
usi
isready
usinewgame
position startpos
perft depth 2 divide
bench nodes 10000
go nodes 5000
quit
usi に対しては次のように応答します(Hayanagi 1.5.1 の出力)。
id name Hayanagi 1.5.1
id author hnakada123
option name USI_Ponder type check default false
option name MultiPV type spin default 1 min 1 max 32
option name USI_ShowCurrLine type check default false
option name USI_ShowRefutations type check default false
option name USI_LimitStrength type check default false
option name USI_Strength type spin default 1 min -15 max 6
option name USI_AnalyseMode type check default false
option name Threads type spin default 1 min 1 max 128
option name Hash type spin default 16 min 1 max 65536
option name USI_Hash type spin default 16 min 1 max 65536
option name MinimumThinkingTime type spin default 0 min 0 max 600000
option name NetworkDelay type spin default 0 min 0 max 600000
option name NetworkDelay2 type spin default 0 min 0 max 600000
option name SlowMover type spin default 100 min 1 max 1000
option name ResignValue type spin default 99999 min 0 max 99999
option name MaxMovesToDraw type spin default 500 min 0 max 600000
option name EnteringKingRule type combo default CSARule24 var NoEnteringKing var CSARule24 var CSARule24H var CSARule27 var CSARule27H var TryRule
option name GenerateAllLegalMoves type check default true
option name USI_OwnBook type check default true
option name BookDir type string default book
option name BookFile type combo default hayanagi_book.db var no_book var hayanagi_book.db
option name TsumeMode type check default false
usiok
copyprotection checking
copyprotection ok
generate_checking_moves)MaxMovesToDraw)EnteringKingRule)usiisreadyusinewgameposition startpos moves ...position sfen ... moves ...go depth Ngo movetime Ngo nodes Ngo ... searchmoves <move1> <move2> ...(探索する初手を指定)go ... movestogo N(次の時間更新までの自分の残り着手数)go ponder ...go infinite(stop まで bestmove を返さない)go mate <ミリ秒|infinite>(標準の詰将棋解答。checkmate で全手順を返す)go wtime ... btime ... byoyomi ...go tsume <attack|defense> depth N movetime M(詰み探索。詳細)setoption name USI_OwnBook value <bool>setoption name BookDir value <path>setoption name BookFile value <file>(no_book / hayanagi_book.db、既定値は hayanagi_book.db)setoption name USI_Ponder value <bool>setoption name MultiPV value Nsetoption name USI_MultiPV value N(MultiPV の別名)setoption name USI_ShowCurrLine value <bool>setoption name USI_ShowRefutations value <bool>setoption name USI_LimitStrength value <bool>setoption name USI_Strength value N(-15〜6。負数は級、正数は段の目安)setoption name USI_AnalyseMode value <bool>setoption name Threads value Nsetoption name Hash value N(MB 単位)setoption name USI_Hash value N(標準名。Hash と同じ置換表を設定)setoption name MinimumThinkingTime value Nsetoption name NetworkDelay value Nsetoption name NetworkDelay2 value Nsetoption name SlowMover value Nsetoption name ResignValue value N実装済みの主要オプションは次のとおりです。
USI_OwnBookBookDirBookFileMultiPVUSI_ShowCurrLineUSI_ShowRefutationsUSI_LimitStrengthUSI_StrengthUSI_AnalyseModeThreadsHashUSI_Hash(Hash の別名)USI_PonderMinimumThinkingTimeNetworkDelayNetworkDelay2SlowMoverResignValueMaxMovesToDrawEnteringKingRuleGenerateAllLegalMovesTsumeModeUSI_OwnBook を有効にすると(デフォルトで有効)、go 時に定跡ファイルを参照し、現局面にヒットすれば探索せずに定跡手を返します。定跡ファイルはやねうら王の DB2016 フォーマット(#YANEURAOU-DB2016 1.00)に対応しています。BookDir で定跡フォルダ(デフォルトは実行ファイルからの相対パス book)、BookFile で定跡ファイル名(デフォルトは hayanagi_book.db)を指定します。選択候補は no_book と hayanagi_book.db の2つで、no_book を指定すると定跡を無効にできます。
以前のファイル名を保存したGUI設定では、BookFile を hayanagi_book.db に選び直してください。
定跡は盤面・手番・持駒で照合し、SFEN の手数が異なる同一局面にもヒットします。
ファイル内で先に現れる合法な候補手を採用します。千日手などの終局判定は定跡より優先し、
予想応手も合法性を確認します。生成ツールが出力する # HAYANAGI_MAX_PLY 30 は、
実際の対局で30手目まで定跡を使う指定です。このコメントがない外部定跡には手数制限を加えません。
tools/build_book.py は、Floodgate の平手・通常初期局面の CSA 棋譜から定跡を生成します。
Python 標準ライブラリと、CMake で生成される hayanagi_book_positions を使います。
補助プログラムは Hayanagi 本体の Position を使用し、序盤の抽出範囲を超えて棋譜全体の合法性を検査します。
KIF、駒落ち、任意の開始局面、CSA の複数レコードをカンマで連結した行は、この取り込み器の対象外です。
初版の入力は Floodgate 公式アーカイブ の2025年分です。 取得先と公式掲載の SHA-256 は以下のとおりです。大量の棋譜ページを個別取得せず、アーカイブを一度取得します。
mkdir -p build/book-work/csa
curl -fL https://wdoor.c.u-tokyo.ac.jp/shogi/archive/wdoor2025.7z -o build/book-work/wdoor2025.7z
sha256sum build/book-work/wdoor2025.7z
# 423504903f211316ec40f9c3d8dcc2e5faf392fc4d1334ede1489242a9d09baa
bsdtar -xf build/book-work/wdoor2025.7z -C build/book-work/csa --no-same-owner --no-same-permissions
ハッシュが一致することを確認してから展開してください。展開には7z対応の bsdtar または7-Zipが必要です。
生成定跡の再配布条件は、2026-10-01時点で確認できていません。
現行定跡 book/hayanagi_book.db は旧名 book/standard_book.db でコミット fa2bfb1 に含まれ、既にリポジトリへ公開されています。
これは許諾確認済みであることを意味しません。追加生成する定跡本体と局面別記録はローカルに保持し、
確認内容を redistribution.json に記録します。
サーバプログラムのGPLを棋譜データのライセンスとはみなしません。
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j 4
python3 -B tools/build_book.py import \
--input build/book-work/csa/2025 \
--validator build/hayanagi_book_positions \
--work-db build/book-work/floodgate2025.sqlite \
--max-ply 30 --min-rating 3000 --min-game-plies 40 \
--source-url https://wdoor.c.u-tokyo.ac.jp/shogi/archive/wdoor2025.7z \
--source-sha256 423504903f211316ec40f9c3d8dcc2e5faf392fc4d1334ede1489242a9d09baa
python3 -B tools/build_book.py export \
--work-db build/book-work/floodgate2025.sqlite \
--output book/variants/local/hayanagi_book.db \
--min-count 3 --min-pairs 2 --pair-cap 16 \
--max-positions 5000 --max-candidates 3 \
--engine build/hayanagi --nodes 100000 --workers 4
# ローカル候補を試す場合は、コピー元を明示して再構成します。
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
-DHAYANAGI_BOOK_SOURCE="$PWD/book/variants/local/hayanagi_book.db"
cmake --build build -j 4
取込時は、両対局者の記録レート3000以上、40手以上、通常の終局記録がある棋譜を対象にします。
棋譜全体の指し手列で重複を除き、そのハッシュで約10%を検証用に分離します。
各局面の候補手には3局以上・異なる対局者の組み合わせ2組以上の支持を要求します。
同じ組み合わせによる寄与は選択用の重みでは16局までに抑え、実際の出現回数は別に保持します。
対局者名はエンジンの独立性を保証するものではありません。
初手候補は既定で 7g7f・2g2f・5g5f(--first-moves で変更可能)です。
--engine を指定すると、まず定跡を無効にした新しい Hayanagi プロセスで全合法手を探索します。
別の新しいプロセスで、その最善手と棋譜由来候補をまとめて MultiPV 探索します。
各探索は既定で10万ノードです。全候補が完了した同じ深さ(3以上)の評価値を比較し、
最良候補より150を超えて低い評価や、負けの詰み評価がついた候補を除外します。
解析方式の版番号をキャッシュキーに含め、以前の異なる深さの評価値を使う記録は再利用しません。
これは浅い探索による選別であり、定跡手の正しさや棋力向上の証明ではありません。
採用候補の並び順は、偏りを抑えた出現頻度順を維持します。棋譜に付属する評価値は流用しません。
--engine を省略すると頻度だけで生成し、評価値・深さは未解析を表す0になります。
出力する hayanagi_book.db は既存の DB2016 形式です。
同名の .json に入力・生成条件・ハッシュ・除外件数・検証棋譜での命中率、
.positions.jsonl に各局面の代表手順・候補の支持数・解析結果を保存します。
検証は未使用棋譜の再生による収録範囲の測定であり、対局成績の測定ではありません。
SQLite は build/book-work/ に置き、完了した解析を局面単位で保存します。
中断後は同じ export コマンドで解析を再開できます。入力条件を変える場合は新しい作業DBに取り込み直してください。
生成された book/hayanagi_book.db がある場合、ビルド時に実行ファイル横の book/hayanagi_book.db へコピーされるため、
既定の USI_OwnBook=true のまま追加設定なしで使えます。未収録局面では通常探索へ戻ります。
ローカルの候補を使う場合は CMake の HAYANAGI_BOOK_SOURCE にそのファイルの絶対パスを指定します。コピー先の名前は hayanagi_book.db です。
GUIから指定する場合は、候補定跡を hayanagi_book.db として配置し、BookDir でそのフォルダを選びます。
本ツールでは評価関数の学習や自己対局による更新はまだ行いません。
python3 -B tests/test_book.py --engine build/hayanagi --validator build/hayanagi_book_positions
tools/match_book.py は、同じ Hayanagi の定跡あり/なしを先後入れ替えで比較します。
評価関数・定跡ファイルは更新せず、固定した生成物の効果を測定します。
1手のノード数、Threads=1、Hash=16 MiB、MultiPV=1、先読みなし、棋力制限なしを両者で揃え、
対局ごとに新しいプロセスを起動します。前の対局の置換表は引き継ぎません。
合法手・終局は hayanagi_match_referee が着手履歴を保持して判定します。
この判定器は Hayanagi の Position を共用し、USI の resign を千日手の負けと誤認しません。
次の例では、生成時に未使用とした棋譜から100局面を固定します。 初手が▲2六歩・▲7六歩・▲5六歩の棋譜から、2・4・6・8手進んだ局面を各25個抽出し、 盤面・手番・持駒の同じ局面を重複させません。定跡に当たるかどうかや評価値では選別しません。 この集合は多様な序盤を比較するためのもので、実戦での出現頻度を再現した標本ではありません。 通常の初期局面も別枠で検証し、同じ決定的な対局を繰り返して統計上の局数を増やしません。
cmake --build build -j 4
python3 -B tools/match_book.py prepare \
--work-db build/book-work/floodgate2025.sqlite \
--output book/evaluation/openings-20260930.json --pairs 100 --seed 20260930
python3 -B tools/match_book.py run \
--engine build/hayanagi --referee build/hayanagi_match_referee \
--book book/hayanagi_book.db --openings book/evaluation/openings-20260930.json \
--output book/evaluation/paired-20260930 --nodes 10000 50000 --max-plies 320 --workers 8
python3 -B tools/match_book.py audit \
--engine build/hayanagi --output book/evaluation/paired-20260930 --nodes 200000 --workers 8
上記は100局面×先後2局×探索量2条件の400局と、初期局面からの4局、計404局です。
入玉は両者とも CSARule24 とし、評価値による投了は無効です。
320手で打ち切った場合は runner_ply_cap の引き分けとして、千日手・持将棋と区別します。
定跡による時間節約を後の手へ再配分しない、ノード数固定の比較です。
games/ に全着手・探索評価・定跡ヒット・終局理由を対局ごとに保存し、
summary.json に定跡側の勝敗と得点率(勝ち1、引き分け0.5、負け0)を集計します。
95%区間は先後2局を1組として10,000回再抽出するブートストラップで求めます。
各探索条件の区間であり、多重比較の補正はしません。関連する戦型同士の相関や、
同一エンジン相手への偏りがあるため、一般的な棋力・対人レーティングへ換算しません。
audit は最後の定跡ヒット後に定跡側が通常探索へ戻った局面と、その4手後・8手後を、
定跡なし・1局面20万ノードの新しい Hayanagi プロセスで解析します。
先後入れ替え対局の同じ色・同じ手数も参考対照として解析しますが、そこに至る手順や相手の定跡設定は異なります。
200以上の評価低下を集計し、終了済みの局面や詰み評価は通常の評価値平均から分離します。
Hayanagi 自身の評価なので、強い外部エンジンによる独立した正しさの検証ではありません。
詳細は exit_windows.json と audit/ に残します。
エンジン・定跡・判定器・開始局面のハッシュと条件は manifest.json に固定します。
同じコマンドを再実行すると完了した対局・解析を再利用します。
条件やファイルを変更して比較する場合は、別の出力ディレクトリを指定してください。
2026-09-30 の生成定跡では、上記404局と定跡離脱前後の813局面の再解析を完了しました。 未使用棋譜の100局面について、定跡側の成績は次のとおりです。
| 1手の探索量 | 勝・負・分 | 得点率 | 95%区間 | 定跡が使われた対局 |
|---|---|---|---|---|
| 10,000ノード | 112・88・0 | 56.0% | 51.0–61.0% | 73/200局 |
| 50,000ノード | 89・105・6 | 46.0% | 41.25–50.75% | 69/200局 |
1万ノードでは改善が見られましたが、5万ノードでは改善を確認できませんでした。 通常の初期局面からの別枠対局も、それぞれ1勝1敗、0勝2敗です。 この結果だけでは、定跡による一貫した棋力向上を確認したとは判断できません。
定跡が使われた対局では、最後の定跡ヒット後に通常探索へ戻る手数の中央値は7手目・8手目でした。
その局面の20万ノード評価が定跡側から見て−200以下だった例は、両条件ともありませんでした。
8手後までに評価値が200以上低下した例は7/73局(9.6%)・4/69局(5.8%)、
平均変化は+24・+75でした。参考対照の定跡なし側では15/73局・12/69局でしたが、
対局経路と相手の設定も異なるため、この差を定跡単独の因果効果とは解釈しません。
最大の低下は1万ノードの holdout_017 先手で、離脱時+95から8手後−1479でした。
全404局・42,448手を再生し、合法性・終局理由・勝敗・開始局面の組合せを照合しました。 320手打切りはなく、終局理由は詰み395局、持将棋判定2局、千日手6局、連続王手の千日手1局です。 集計は summary.json、 再生検証は validation.json、 離脱前後の評価は exit_windows.json に保存しています。 次の改良では、定跡が続く範囲の拡大と、離脱後に大きく評価を落とした局面の追加検証が候補です。
tools/diagnose_book.py は、保存済みの対局と定跡離脱後の解析結果を使って、
定跡手と通常探索のどちらに改善候補があるかを調べます。
定跡を実際に使った5万ノード条件の敗局について、自分の手番ごとに終局まで50万ノードで再解析します。
以前の検証で離脱後8手以内に評価が200以上落ちた対局も、勝敗を問わず対象にします。
全対局で実際に使われた定跡手、最初の通常探索の手、評価急落の直前の手などを抽出します。 各局面の全合法手探索と、実戦の手・再探索の推奨手に制限した MultiPV 探索を、 別々の新しいプロセスで各200万ノード実行します。候補間の評価差は、 全候補の正確な評価がそろった同じ完了深さで計算します。 全定跡手と、通常探索で200以上の差または詰みの差が出た手は、各1,000万ノードで再確認します。
python3 -B tools/diagnose_book.py \
--matches book/evaluation/paired-20260930 \
--output book/evaluation/diagnosis-20260930 --workers 8
条件と入力のハッシュは manifest.json、対象局面は plan.json に固定し、
解析は analysis/ に保存します。同じコマンドで中断後に再開できます。
comparisons.json に実戦手・代替手・SFEN・手順・完了深さ・評価差、
trajectories.json に敗局の評価推移、loss_classification.json に分類を残します。
終局直前の自分の手は「次の自分の手番との評価差」で拾えないため、
予備解析で−200以上または勝ちの詰み評価なのに直後に負けた未調査の最終着手を、
terminal_followup.json で補足します。
補足対象と条件は terminal_followup/manifest.json に別途固定します。
通常探索の問題候補は予備解析から選ぶため、すべての着手の網羅的な品質検査ではありません。
Hayanagi 自身の評価関数による診断なので、評価関数の偏りや深さによる評価変動は残ります。
評価差は改善候補を示すもので、着手を変えれば勝敗が逆転するという証明ではありません。
今回の結果を改良に使う場合、改良後の最終評価には別の未使用局面を用意します。
2026-09-30 の原因調査では、2,500局面を予備解析し、376件の着手と終局直前の補足2件を比較しました。 評価差の確認は上限1,000万ノード、同じ完了深さの MultiPV で行いました。
| 調査対象 | 結果 |
|---|---|
| 実際に使われた定跡手100件 | 代替手との評価差は最大81。150以上の差は0件 |
| 定跡を使った5万ノード条件の41敗 | 37局に通常探索の問題候補、追加検査で1局に詰み探索のルール判定不具合、残る3局は原因未特定 |
| 初期局面からの5万ノード条件の2敗 | 両局に通常探索の問題候補 |
| 上記43敗の定跡離脱時点 | 200万ノード評価は最低−31、平均+50.1。−200以下は0局 |
通常探索の問題候補は、代替手との差200以上、または詰み評価の差が再確認できたものです。
本調査は通常探索の候補を選別しており、すべての悪手を検出したわけではありません。
37局の分類は loss_classification.json、
追加検査を含む結論は findings.json に保存しています。
主分類の「未特定4局」のうち 50000-holdout_049-b は、追加検査で次の不具合が判明しました。
50000-holdout_049-b の67手目は、
6a7a を指すと直ちに連続王手の千日手で負けますが、エンジンは mate 3 を返してこの手を選びます。
Search::mate_search_attack / mate_search_defense は再帰中に terminal_status() を確認していません。
同じ局面・5万ノードでも、全合法手を searchmoves に指定して冒頭の詰み探索を省くと、
3a4a を選び、この即時の負けを避けます。これ自体は以後の勝利の保証ではありません。
再現手順と生出力は perpetual_check_probe.json にあります。50000-holdout_070-b の59手目▲9一角成は、
△7八飛打で詰みます。対局時の完了深さは1でした。代替の▲8八金打なら、同じ飛打に▲同金と取れます。
この違いは評価値だけでなく、合法手と終局判定でも確認しました。
記録は mate_validation.json にあります。50000-holdout_099-b の17手目▲7七桂は−529、
代替の▲7七銀は−9で、深さ10の比較で差520でした。▲7七銀は△8八角打に備えられます。
また 10000-holdout_017-b の9手目▲2五歩打は飛車の退路を塞ぎ、
▲2八飛との差は深さ13で1489でした。この対局は最後には勝っており、局所的な失敗と勝敗は区別しています。別途、50000-holdout_042-b の123手目では、50万ノードでも深さ1を完了できず、
静止探索で予算を使い切る挙動を再現しました。詰み探索を省く条件でも発生します。
5万ノードの元対局で評価値が出なかった通常着手は、定跡側・定跡なし側とも53回でした。
この問題だけで定跡側の得点差を説明できるとは判断していません。
再現記録は search_budget_probe.json にあります。
今回の優先修正箇所は、詰み探索中の終局ルール判定と、浅い探索で即詰みを見落とす挙動です。 定跡の大幅な評価劣化は今回の範囲では確認されませんでしたが、Hayanagi自身の評価による結果です。 元の得点率46%の95%区間も50%を含むため、定跡が一般に棋力を下げたと断定する結果ではありません。 報告した1,132本の読み筋を合法手として再生し、評価差の計算とエンジン・定跡のハッシュを照合済みです。 詳細は validation.json に保存しています。
上記の調査後、通常対局の詰み探索でも着手履歴を更新し、各節点で終局ルールを確認するようにしました。
履歴を更新しない make_move では、終局判定を追加するだけでは連続王手の千日手を検出できないため、
この探索では履歴を保存する do_move を使います。
深さ1の末端でも、駒を取らない王手・駒打ちによる1手詰めを確認します。
静止探索は通常探索の深さとは別に最大6手までとし、境界で王手されている場合は合法な応手を評価します。 冒頭の5手詰め探索にもノード・時間の部分予算を設けました。 反復深化が完了しない場合にも評価済みの合法手を返すため、先に浅い候補比較を行います。 極端に小さい探索量では、この比較自体が完了する保証はありません。 王手になる駒取りは、単純な駒の交換損だけを理由に静止探索から除外しません。
評価関数には、敵に攻撃され味方に守られていない歩以外の駒の割引と、 飛車の安全な移動先が少ない場合の減点を追加しました。どちらも先後共通の規則で、特定の棋譜や手順は参照しません。 係数は手作業による初期値です。駒の利きに基づく近似であり、学習済み評価関数や完全な戦術判定ではありません。
修正前と同じ棋譜履歴・ノード数で、新しいプロセスから探索した結果です。
| 再現例 | 修正前 | 修正後 |
|---|---|---|
049・67手目、5万ノード | 6a7a を3手詰めと誤認し、連続王手で即負け | 4d4b+ を選択し、即負けを回避 |
070・59手目、5万ノード | 6d9a+ の直後に1手詰め | G*6h を選択。深さ1制限でも即詰みを回避 |
042・123手目、5万ノード | 深さ1を完了せず 5i4i | 深さ4まで完了して P*6c |
099・17手目、5万ノード | 角打ちを許す 8i7g | 6g6f |
017・9手目、1万ノード | 飛車の退路を塞ぐ P*2e | 2d2f |
上限1,000万ノードの候補制限 MultiPV でも比較し、最後の2例は修正前の評価関数でも、 新しい着手がそれぞれ500・1701高い評価でした(各比較は同じ完了深さ11・14)。 詰み・千日手・読み筋は合法手として再生して検証します。 元対局の5万ノード条件で評価値が出なかった106着手は、すべて新しい探索で評価値が出ました。 1万ノード条件では168着手中151着手で改善し、17着手では完了した反復の評価値が出ませんでした。 局面の再生は重複を含み、両条件合計の独立した入力履歴は200件です。
テスト入力は tests/fixtures/search_regressions.json にあり、大きな棋譜データを必要としません。
修正前バイナリでは8件のサブテストが失敗し、修正後はすべて成功します。
連続王手、深さ1の即詰み回避、静止探索の予算、微小予算での初手制限は1・4スレッドで検証します。
ctest --test-dir build --output-on-failure
python3 -B tests/test_engine.py build/hayanagi
python3 -B tests/test_search_regressions.py \
--engine build/hayanagi --referee build/hayanagi_match_referee \
--report book/evaluation/search-fixes-20260930/regressions-after.json
個別局面の比較は comparisons.json、
評価値の出力状況は score-coverage.json、
再発防止テストの記録は regressions-after.json に保存しています。
通常の戦術ミスがすべてなくなったという結果ではありません。
追加比較した 083 の55手目では、新しい選択手が深い探索で以前の手より低く評価される例もあります。
局面ごとの改善と、対局全体の改善は分けて検証します。
対局評価には、以前の100局面とSFENが重複しない新しい100局面を固定しました。 短い手順では未使用局面が少ないため、2・4・6・8手の内訳は5・32・32・31局面です。 以前の集合と分布が異なるので、得点率をそのまま前後比較しません。 修正前後の直接対戦は両者とも定跡を切り、同じ新局面・探索量・先後交換で比較します。 定跡あり/なしの比較は別に実施します。
python3 -B tools/match_book.py prepare \
--work-db build/book-work/floodgate2025.sqlite \
--exclude-openings book/evaluation/openings-20260930.json \
--output book/evaluation/search-fixes-20260930/openings.json --pairs 100 --seed 20260931
python3 -B tools/match_search.py \
--engine build/book-evaluation-bin/hayanagi-after-search-fixes \
--baseline build/book-evaluation-bin/hayanagi-before-search-fixes \
--openings book/evaluation/search-fixes-20260930/openings.json \
--output book/evaluation/search-fixes-20260930/engine-matches --workers 6
python3 -B tools/match_book.py run \
--engine build/book-evaluation-bin/hayanagi-after-search-fixes \
--openings book/evaluation/search-fixes-20260930/openings.json \
--output book/evaluation/search-fixes-20260930/book-matches --workers 6
python3 -B tools/validate_matches.py --output book/evaluation/search-fixes-20260930/engine-matches
python3 -B tools/validate_matches.py --output book/evaluation/search-fixes-20260930/book-matches
build/book-evaluation-bin/ の実行ファイルは、この修正の前後に保存したローカルの比較用コピーです。
対局条件と実行ファイルのハッシュは各 manifest.json に固定しています。
異なるビルドで再評価する際は別の出力ディレクトリを使います。
修正前後の直接対戦404局を完了しました。新しい100局面の先後交換200局について、修正後の成績は次のとおりです。
| 1手の探索量 | 修正後の勝・負・分 | 得点率 | 先後ペア単位の95%区間 |
|---|---|---|---|
| 10,000ノード | 116・83・1 | 58.25% | 51.5–65.0% |
| 50,000ノード | 111・87・2 | 56.0% | 49.5–62.25% |
初期局面の別枠は両条件とも1勝1敗でした。1万ノード条件で改善が見られましたが、 5万ノード条件の区間は50%を含みます。ノード数固定・この相手と開始局面に対する結果であり、 同じ持ち時間での向上や一般的なレーティングを保証しません。 対局記録と集計は engine-matches/summary.json にあります。
修正後エンジン同士の定跡あり/なし404局も完了しました。同じ新規100局面での定跡側の成績です。
| 1手の探索量 | 定跡側の勝・負・分 | 得点率 | 先後ペア単位の95%区間 |
|---|---|---|---|
| 10,000ノード | 108・92・0 | 54.0% | 50.0–58.0% |
| 50,000ノード | 107・92・1 | 53.75% | 49.25–58.25% |
どちらの区間も50%を含むため、定跡単独の優位性が確立したとは判断しません。
修正前後のエンジン比較と混ぜずに、book-matches/summary.json に保存しています。
両対局群の棋譜は tools/validate_matches.py で再生し、合法手・終局理由・先後の組合せ・勝敗・定跡ヒットを照合しました。
build/hayanagi と build-hayanagi/hayanagi の両方で、追加設定なしに独自定跡を読み込み、
初手 2g2f を返すことも確認しています。
最終候補は11,409局面・19,735候補手です。旧版の4,710局面・9,561候補手から収録範囲を広げました。 支持数の条件を維持して対象を5,000局面から12,000局面へ広げ、 通常探索の修正後エンジンで各探索20万ノードの選別を行います。 旧版から先頭候補が変わった序盤の12局面を200万ノードで追加解析し、 評価が不安定だった2局面を1,000万ノードで確認したところ、候補が選別基準を外れました。 その2局面は、棋譜由来の全候補を1,000万ノードで再選別しています。 根拠は changed-moves-confirmation.json、 最終選択は reviewed-positions.json にあります。 自エンジンの評価による修正で、全候補手の正しさを証明するものではありません。
旧版は book/variants/20260930/、予備候補は book/variants/20261001/、
最終候補は book/variants/20261001-reviewed/ に分けます。
定跡本体と局面別の由来記録はローカルに保持し、集計・選別根拠・検証結果をGitに保存します。
旧版は公開済み book/hayanagi_book.db から復元できます。以下の過去の検証用スナップショットは、記録との対応を保つため旧名 standard_book.db を維持しています。
以下の比較用エンジンは、解析開始前に build/hayanagi をコピーして固定したものです。
再実行時は別の出力先を指定してください。保存されたハッシュと違うエンジン・定跡・対局ツールでの再開は拒否されます。
python3 -B tools/build_book.py export \
--work-db build/book-work/floodgate2025.sqlite \
--output book/variants/20261001-reviewed/standard_book.db \
--min-count 3 --min-pairs 2 --pair-cap 16 --max-positions 12000 --max-candidates 3 \
--engine build/book-evaluation-bin/hayanagi-book-v2 --nodes 200000 --workers 12 \
--review-positions book/evaluation/book-v2-20261001/review-positions.json --review-nodes 10000000
python3 -B tools/validate_generated_book.py --book book/variants/20261001-reviewed/standard_book.db
python3 -B tools/compare_books.py \
--engine build/book-evaluation-bin/hayanagi-book-v2 \
--current book/variants/20260930/standard_book.db \
--candidate book/variants/20261001-reviewed/standard_book.db \
--openings book/evaluation/book-reviewed-20261001/openings.json \
--output book/evaluation/book-reviewed-20261001/comparison
python3 -B tools/validate_book_comparison.py \
--current book/variants/20260930/standard_book.db \
--candidate book/variants/20261001-reviewed/standard_book.db \
--output book/evaluation/book-reviewed-20261001/comparison \
--work-db build/book-work/floodgate2025.sqlite --archive-games
最終検証の条件は対局開始前に plan.json に固定しています。
検証局面は、過去3つの検証集合と局面・元棋譜が重ならない未使用40棋譜から1局面ずつ抽出しました。
先頭4/6/8手を順番に選び、定跡命中や評価値・対局結果では選別しません。
元棋譜が学習から除外されていることも openings.validation.json で照合します。
分離は棋譜単位であり、学習棋譜と同一の定跡局面が現れることはあります。
過去の原因解析の根局面まで追加照合すると2局面に重複があったため、
予定した40局面の結果を保存したうえで、重複を除いた38局面の補足集計も行います。
validate_book_comparison.py --prior-analysis で検査し、対局結果による除外は行いません。
抽出は tools/prepare_book_comparison.py --pairs 40 --seed 20261002 で行い、
--exclude-openings に過去3つの開始局面ファイルを指定します。
現行版・最終候補・定跡なしの全3組を先後交換します。 5万ノード制と持ち時間制で、それぞれ40局面を使用します。 各組・各条件に初期局面の2局を別枠で加え、合計492局です。 持ち時間は各5秒+秒読み100ms、エンジンの余裕10msです。 各開始局面で双方の時計を5秒に設定し、固定した開始手順の消費時間は加算しません。 実消費時間を毎手切り上げて差し引き、定跡で節約した時間を後の探索に使えます。 生成とノード制対局を終えてから、4物理コアに分けて持ち時間制対局を行います。 短い持ち時間での比較であり、大会の持ち時間や他エンジンへの一般化は保証しません。
games/ に時計と定跡照合を含む全記録、summary.json に先後ペア単位の集計を保存します。
Gitには検証後の棋譜を games.zip に圧縮して保存します。再生検証ツールはZIPも直接読み込めます。
同じ条件で対局を再開する場合は、先にZIP内のJSONを games/ へ展開します。
再生検証は合法手・定跡の選択順・時計の繰り越し・時間切れ・勝敗・集計を確認します。
異なる対局経路の残り時間の差は、定跡による時間節約の厳密な因果推定とはみなしません。
先行した852局の予備比較は book/evaluation/book-v2-20261001/ に保存します。
その時計条件の一部は2局面の再選別処理と実行が重なったため、時間の比較は参考扱いとし、
最終候補の時計条件では追加解析・生成・ノード制対局を同時に実行しません。
最終492局と予備852局、計1,344局の再生検証を完了しました。 最終検証の40局面・先後交換80局ずつの結果は次のとおりです。
| 条件 | 得点率を示す側/相手 | 勝・負・分 | 得点率 | ペア単位の95%区間 |
|---|---|---|---|---|
| 5万ノード | 最終候補/現行版 | 41・39・0 | 51.25% | 43.75–58.75% |
| 5万ノード | 最終候補/定跡なし | 40・40・0 | 50.00% | 42.50–57.50% |
| 5万ノード | 現行版/定跡なし | 41・39・0 | 51.25% | 47.50–55.00% |
| 5秒+100ms | 最終候補/現行版 | 37・43・0 | 46.25% | 35.00–57.50% |
| 5秒+100ms | 最終候補/定跡なし | 33・47・0 | 41.25% | 31.25–51.25% |
| 5秒+100ms | 現行版/定跡なし | 42・38・0 | 52.50% | 43.75–61.25% |
全ての区間が50%を含み、候補版の棋力向上は確認できませんでした。 過去の解析との重複を除いた38局面でも、候補版の対定跡なし得点率はノード制48.68%、持ち時間制40.79%でした。 初期局面の別枠は全組・両条件とも1勝1敗、最終検証の時間切れは0局です。 そのため、既定の定跡には現行版を採用し、収録を拡大した候補版はローカルの検証用として保存します。
持ち時間制の対定跡なしでは、定跡を使えた対局は現行版13/80局、候補版24/80局でした。 候補版の定跡応答は平均0.18ms、通常探索は平均135msで、残り時間に節約分を繰り越す動作は確認できました。 定跡を使った対局での離脱手数の中央値は現行版9手目、候補版10.5手目でした。 ただし、開始手順を固定した試験での集計であり、初手からの全対局を代表する標本ではありません。 局面と対局経路が異なるため、応答時間の差をそのまま因果的な節約量とはみなしません。 収録範囲の拡大や時間の節約が、今回の対局成績の改善につながったとは判断できません。
集計は summary.json、 再生確認は validation.json、 38局面の補足集計は novelty.json、 採用判断は findings.json に保存しています。
公式アーカイブと 公開方針の記録では棋譜の公開を確認しましたが、 生成定跡の再配布に適用できる明示的な条件は、確認したページでは見つかりませんでした。 確認先と未確認事項は redistribution.json、出典表示は NOTICE.txt にあります。 これは利用・再配布が全て禁止という法的判断ではありません。運営者への問い合わせは行っていません。
tools/package_release.py は実行ファイルと book/hayanagi_book.db を同じ親ディレクトリに配置し、
出典・生成条件・同梱物のSHA-256を付けたZIPを作ります。
定跡の許諾が未確認の間は --purpose preview でローカルの配置確認用ZIPを作れます。
定跡を同梱する --purpose release は、確認済み状態と根拠URL・許諾内容・対象アーカイブの一致を必要とします。
定跡なしの実行ファイルだけのZIPも作れます。コマンドはGitHubへの公開操作を行いません。
python3 -B tools/package_release.py --engine build/hayanagi \
--book book/variants/20261001-reviewed/standard_book.db --purpose preview \
--output build/release-candidate/hayanagi-book-preview.zip
python3 -B tools/package_release.py --engine build/hayanagi --purpose release \
--output build/release-candidate/hayanagi-engine.zip
cmake --install build --prefix "$PWD/build/release-stage" --component Runtime
通常のCMake installは実行ファイルと説明書を配置します。 ローカルで候補定跡を既定として使うには、次のようにビルド先へコピーします。
cmake -S . -B build -DHAYANAGI_BOOK_SOURCE="$PWD/book/variants/20261001-reviewed/standard_book.db"
cmake --build build -j 4
MultiPV を有効にすると、info ... multipv N pv ... を順位ごとに出力します。GenerateAllLegalMoves は互換性維持のため残していますが、現在は探索強度を落とさないよう no-op です。
USI_LimitStrength は既定で false です。true にすると USI_Strength(既定1、範囲-15〜6)に応じて
探索の基本深さとノード数を制限します。負数は級、正数は段の目安、0は1級相当として扱います。
段級位は対局による校正前の目安であり、実際の人間の段級位に一致する保証はありません。
探索量の代表値は以下のとおりです。基本深さの先では通常どおり静止探索を行います。
USI_Strength | 基本深さの上限 | ノード数の上限 |
|---|---|---|
| -15 | 1 | 256 |
| -10 | 2 | 1,536 |
| -5 | 4 | 8,192 |
| -1 / 0 | 5 | 32,768 |
| 1 | 6 | 49,152 |
| 6 | 7 | 262,144 |
go depth / nodes がより小さければそちらを優先し、時間制限も守ります。
並列探索の停止処理ではノード数がワーカー数程度超過する場合があります。
棋力制限中は定跡による即答と独立した詰み事前確認を使わず、置換表は今回の探索のワーカー間だけで共有します。
過去の強い探索や同じ弱い探索の繰り返しによって、制限を越えた読みを流用しません。
USI_LimitStrength が false の場合、USI_Strength は探索に影響しません。
USI_AnalyseMode は既定で false です。true にすると棋力制限、定跡による即答、
ResignValue による自動投了、bestmove の先読み要求を無効にします。
詰みや入玉などの終局判定と、明示した探索深さ・ノード数・時間の指定は維持します。
解析モード自体は時間無制限の指定ではないので、時間無制限の検討には go infinite を併用してください。
false に戻すと、保存してある元の棋力・定跡・投了・先読み設定で通常対局に戻ります。
これらの設定変更は次の go から適用します。go infinite は stop、go ponder は stop または
ponderhit まで返答を待ちます。対局用の棋力制限は go mate / go tsume / bench / perft には適用しません。
setoption name USI_LimitStrength value true
setoption name USI_Strength value -5
position startpos
go btime 60000 wtime 60000 byoyomi 1000
searchmoves は初手だけを制限します。例えば go depth 6 searchmoves 7g7f 2g2f は、
その2手のいずれかを初手とする手順を探索します。定跡も指定された合法手から選び、
詰み確認や中断時の代替手が制限を迂回することはありません。重複・不正・非合法な指し手は除き、
候補が空なら bestmove resign を返します。制限は次の go に引き継ぎません。
MultiPV の出力数は制限後の合法な候補数が上限です。
movestogo N を指定すると、持ち時間を N で割った値を時間配分の基準にします。
未指定または N が0以下なら従来の30手分配を使います。加算・秒読み・通信遅延・
持ち時間による上限も適用し、movetime 指定がある場合はそちらを優先します。
Threads は通常探索、通常探索前の詰み確認、go mate / go tsume / bench tsume、perft に適用されます。
既定値は 1、範囲は 1〜128 です。例えば setoption name Threads value 4 で計算を最大 4 スレッドに分担します
(USI コマンドを受け付けるスレッドは別)。小さい探索では管理コストを避けるため逐次処理し、
perft は深さ 3 以上で並列化します。divide の出力順と各統計はスレッド数によらず同じです。
通常探索の info には depth / seldepth / score cp / nodes / time / nps / hashfull / cpuload / pv を出力します。
詰みを見つけた場合は score mate N、詰まされる場合は score mate -N で手数を通知します。
入玉宣言や連続王手の千日手による勝敗は詰みとは区別します。
探索中は約1秒間隔でノード数・ハッシュ使用率・現在の候補手 currmove と、探索順で1から数えた currmovenumber も通知します。
cpuload は探索開始以降のプロセス CPU 時間を、経過時間と実際の探索ワーカー数で割った使用率です。
全ワーカーを使い切った状態を1000とし、0〜1000で通知します。CPU 時間を取得できない環境では省略します。
通常探索の SinglePV では深さ5以降、直前の評価値の周囲を先に調べる aspiration window を使います。
評価値が探索窓を外れた場合は、確認できた下限に lowerbound、上限に upperbound を付けて通知します。
その後は探索窓を広げて再探索し、値が確定するまで完了深さと最善手を更新しません。
再探索中の stop では、最後に完了した反復の最善手を返します。
USI_ShowCurrLine を true にすると、各ワーカーの探索中の合法手順を info currline <番号> <手順> で通知します。
ワーカー番号は1から始まり、全ワーカー分をまとめて約1秒間隔で出力します。手順は約100ミリ秒間隔で採取し、
待機中のワーカーは手順を空にします。探索内部の null move より先は通知しません。
USI_ShowRefutations を true にすると、各候補手について探索から得られた応手・手順を info refutation <初手> <応手…> で通知します。
応手が得られていない場合は初手だけを返し、探索中の定期通知と探索終了時に出力します。
両オプションとも既定は false で、次の go から反映します。
debug on は受信コマンドや探索の時間配分を info string debug ... で通知します。
既定は off です。探索中でも debug on / debug off を切り替えられます。
USI_Ponder を有効にすると、通常探索の bestmove は bestmove <move> ponder <move> を返します。go ponder で始めた探索は ponderhit または stop を受けるまで bestmove を返しません。
go infinite は、詰みや終局を検出した場合も stop を待ちます。無制限探索では定跡による即時返答を行いません。
gameover / position / usinewgame / quit は古い探索結果を破棄します。
コマンドは LF・CRLF に対応し、BookDir には空白を含むパスも指定できます。
将棋所のUSI仕様に掲載された原案の未対応コマンド一覧のうち、
Hayanagi では利用者登録用の register / registration を除いて実装しています。
copyprotection はエンジンからGUIへの通知です。usiok の後に copyprotection checking と
copyprotection ok を返します。公開版にはコピー制限がないため確認結果は常に利用可であり、
ライセンス認証・登録処理・外部への問い合わせは行いません。
searchmoves / movestogo や追加の探索情報の意味は USI原案 に従います。
これらの追加機能は将棋所自身では未対応のため、対応 GUI や検証ツールから利用してください。
Positionstartpos / sfen の読み込み、USI 指し手の適用、合法手生成を担当します。generate_checking_moves)は、移動先に置いた駒が相手玉に利く升と開き王手の候補を先に求め、該当する手だけを列挙します。並び順は全合法手の生成順と同じです。make_move / unmake_move は履歴を更新しない軽量な着手・待ったで、詰み探索のように千日手判定が不要な探索で局面のコピーを省きます。has_legal_move は手を列挙せずに合法手の有無を判定します(王手回避では玉の移動・王手駒の捕獲・合駒の順に調べます)。TsumeSearchSearchnegamax + alpha-beta 探索を行います。Threads > 1 のときは root move 単位で並列探索します。go nodes 指定時は毎ノード反映して停止判定の精度を保ちます。Hash オプションでサイズ変更できる lockless 共有置換表、PVS、quiescence search、SEE ベースの着手順序、killer/history heuristic、LMR、null-move pruning を使って探索効率を上げています。src/evaluation.cpp の evaluate_position() が担当し、駒得に加え、駒の前進度、利きの広さ、敵陣進出、手駒価値、玉の安全度を見ます。終局判定と確定スコアの値域への制限は Search が担当します。Book#YANEURAOU-DB2016 1.00)を読み込みます。# HAYANAGI_MAX_PLY コメントから読み込みます。UsiEngineusi / isready / position / go / stop / quit を処理します。stop に反応できる構成にしています。isready 時に定跡ファイルを読み込み、go 時に定跡を参照します。bench と perft を内蔵しており、GUI 接続前の自己確認にも使えます。bench tsume は詰み探索の固定局面を順に解き、結果とノード数・時間を出力します(出力例)。bestmove がないため、千日手・持将棋など現在局面でゲーム終了と判定した場合は info string terminal ... を出した上で bestmove resign を返します。perft は nodes に加えて captures / promotions / checks / mates を出力します。bench は各局面と合計について nodes / time / nps / hashfull を出力し、nodes N 指定で固定ノード数ベンチとして使えます。src/tsume.h の TsumeSearch は、通常の評価値探索と分けて、王手の連続による強制詰みを探索します。
玉方ではすべての合法応手を調べ、詰む場合は最長抵抗、不詰の場合は逃れる手を返します。
攻方の玉を省略した SFEN も扱えます。
mate の plies は最短の詰み手数です。make_move / unmake_move で進めて戻し、局面のコピーと履歴の確保をしません。TsumeSearch を続けて使うと、攻方が同じ間は前回の証明を再利用します(PV の再構成や別詰の数え上げが速くなります)。threads > 1 を渡すと、十分な探索量がある局面の候補手を並列に調べます。玉方の応手が少ないときは、次の攻方の王手で分担します。各ワーカーは独立した局面・置換表を持ち、反復深化の間は再利用します(置換表の最大 32 MB はワーカーごと)。TsumeSearch と Position はグローバルな可変状態を持たないので、スレッドごとに別インスタンスを持てば並行して使えます。go mate現在手番を攻方として解答します。制限時間は手数ではなくミリ秒です。
攻方の玉を省略した局面でも、TsumeMode を設定せずに利用できます。
position sfen 9/9/6R1+R/5k3/9/7+S1/9/9/9 b 2b4g3s4n4l18p 1
go mate 5000
応答例:
checkmate 3c5c+ 4d4e 1c4c P*4d 4c4d
checkmate nomate を返します。stop には checkmate timeout を返します。通常探索の bestmove は返しません。go mate infinite は時間制限なしで探索し、詰み・不詰が確定した時点で返答します。info string で通知し、期限または stop まで待って checkmate timeout を返します。position / gameover / quit による中断では結果を破棄します。TsumeSearch::solve では time_limit_ms == 0 が時間無制限です。USI の go mate 0 は制限時間0ミリ秒として扱います。go tsume単独実行時は次の独自 USI 拡張を利用できます(通常 USI の go mate とは別のコマンドです)。
usi
setoption name TsumeMode value true
setoption name USI_OwnBook value false
isready
position sfen 9/9/6R1+R/5k3/9/7+S1/9/9/9 b 2b4g3s4n4l18p 1 moves 3c5c+
go tsume defense depth 4 movetime 5000
応答例:
tsume mate move 4d4e plies 4 nodes ...
attack は現在手番を攻方、defense は現在手番を玉方として探索します。depth は現在局面からの最大手数(既定 31、上限 63)、movetime はミリ秒(既定 5000)です。mate / nomate / depthlimit / timeout / cancelled です。不正な局面・コマンドでは tsume invalid を返します。nomate は不詰の証明です。depthlimit は指定手数以内に詰みがないという意味で、それより長い詰みの否定ではありません。timeout / cancelled は未判定です。move は攻方の詰め手、または玉方の抵抗・逃れの手です。着手がない場合は none です。plies は証明された詰みまでの手数で、mate の場合に有効です。stop で中断結果を返し、position / quit は進行中の探索を破棄します。TsumeMode は既定 false です。片玉局面で独自拡張の go tsume を使う場合は true にします。標準 go mate は設定不要ですが、片玉局面での通常の go は拒否します。bench tsumebench tsume [movetime M] は BENCHMARK.md と同じ 8 局面を順に解き、局面ごとの結果と合計を info string で出力します(TsumeMode の設定は不要です)。
info string bench tsume 1/8 mate5-1 depth 5 status mate move 3c5c+ plies 5 nodes 646 time 0 nps 646000
...
info string bench tsume 8/8 nomate5 depth 5 status depthlimit move R*7i plies 0 nodes 1870972 time 207 nps 9038512
info string bench tsume total positions 8 nodes 2019874 time 225 nps 8977217
ShogiBoardQ は Hayanagi をサブモジュールとして取り込み、add_subdirectory で静的ライブラリ hayanagi_tsume をリンクしています。
add_subdirectory(Hayanagi)
target_link_libraries(my_app PRIVATE hayanagi_tsume) # include パス(src/)も伝播する
message(STATUS "Hayanagi ${HAYANAGI_VERSION}") # 組み込み側からバージョンを参照できる
hayanagi_tsume は src/position.cpp と src/tsume.cpp だけからなり、Qt などへの依存はありません。hayanagi_tests を既定でビルドしません。必要なら -DHAYANAGI_BUILD_TESTS=ON を指定します。src/position.h、src/tsume.h):
Position::set_sfen(sfen, tsume): tsume=true で攻方の玉がない局面も受け付け、不正な SFEN では false を返します。Position::generate_legal_moves(): 打ち歩詰めを除いた全合法手。generate_checking_moves(): 合法な王手だけ(打ち駒を含み、成・不成は別の手)。どちらも生成順は安定しており、組み込み側が依存できます。Position::apply_usi_move / do_move / make_move / unmake_move / has_legal_move / to_sfen / move_to_usi。TsumeSearch::solve(position, attacker, max_plies, time_limit_ms, stop, threads = 1): TsumeResult{status, move, plies, nodes} を返します。従来の 5 引数呼び出しも利用できます。max_plies は 63、threads は 1〜128 に丸められ、stop は他スレッドから立てると速やかに Cancelled で戻ります。CMake ターゲットは Threads::Threads を依存先に公開しています。ビルド後、Python 3 の標準ライブラリだけで通常将棋と詰将棋の USI 動作を検証できます。
python3 tests/test_engine.py build/hayanagi
# 変更前の実行ファイルがあれば、通常将棋 4 局面の perft 結果も比較する
python3 tests/test_engine.py build/hayanagi --baseline /path/to/previous/hayanagi
python3 tests/test_engine.py build/hayanagi --threads 4 --baseline /path/to/previous/hayanagi
# 同じスレッド設定で通常探索と perft の実時間を比較(各 5 回の中央値)
python3 tests/bench_threads.py build/hayanagi --baseline /path/to/previous/hayanagi
# 詰み探索を 4 スレッドで計測
python3 tests/bench_tsume.py build/hayanagi --threads 4 --baseline /path/to/previous/hayanagi
平手初期局面の perft、通常探索の合法着手、5 手詰 5 問、別解、不詰、手数超過、
後手攻方、打ち歩詰め、入力不正、時間切れ、中止・局面切替、id name の形式を検証します。
標準 go mate の全手順、符号付き詰みスコア、USI_Hash、gameover、
詰み・定跡がある場合の無制限探索、先読み、CRLF、空白付き定跡パス、探索情報の出力も検証します。
初手制限と定跡・MultiPV・中断の組み合わせ、残り着手数による時間配分、診断切り替え、
全ワーカーの合法な探索手順・反駁手順・CPU 使用率、上下限からの再探索と中断も検証します。
棋力制限の上限・切り替え・置換表の分離、初手制限や先読み待機との組み合わせ、
解析モードでの定跡・投了抑止と設定の復帰、コピー保護通知の順序も検証します。
C++ の単体テスト hayanagi_tests は、Hayanagi 自体をビルドしたときだけ既定で生成されます
(add_subdirectory で組み込んだ場合は -DHAYANAGI_BUILD_TESTS=ON で有効化)。
./build/hayanagi_tests
# または
ctest --test-dir build
ランダム局面と平手からのランダム対局について、合法手生成・王手生成・has_legal_move・
make_move / unmake_move を単純な参照実装と突き合わせ、詰み探索については
Limit と NoMate の区別、最短手数、PV の再構成、stop と時間切れ、打ち歩詰め、
玉なし局面、持駒の多い局面、同じ探索器の再利用を検証します。
詰み探索のベンチマークは BENCHMARK.md に記録しています。再計測は次のとおりです。
python3 tests/bench_tsume.py build/hayanagi [--baseline /path/to/previous/hayanagi]
# USI から直接実行する場合
./build/hayanagi <<< $'bench tsume\nquit'
| パス | 内容 |
|---|---|
src/types.h, src/bitboard.h | 基本型、81 升ビットボード |
src/position.h/.cpp | 局面、SFEN、合法手・王手生成、終局判定 |
src/tsume.h/.cpp | 詰み探索 TsumeSearch |
src/search.h/.cpp | 通常対局用の探索 |
src/evaluation.h/.cpp | 駒の価値・配置・利き・玉の安全度による静的評価 |
src/parallel.h | 再利用可能な並列ワーカー群 |
src/book.h/.cpp | 定跡の読み込み |
src/usi_engine.h/.cpp, src/main.cpp | USI プロトコル処理、bench / perft |
src/cpu_time.h | CPU 使用率通知のためのプロセス CPU 時間計測 |
src/version.h | バージョン定義(HAYANAGI_VERSION) |
tests/test_engine.py | USI 回帰テスト |
tests/test_*.cpp, tests/test_support.h | C++ 単体テスト |
tests/bench_tsume.py | 詰み探索ベンチマーク |
tests/bench_threads.py | 通常探索・perft のスレッド数別ベンチマーク |
BENCHMARK.md | ベンチマークの計測結果 |
docs/index.html | Hayanagi の紹介ページ(機能・使い方・主な設定・教材への案内) |
docs/textbook.html, docs/chapter*.html | 将棋エンジンの仕組みを解説するHTML教材(全15章) |
docs/style.css, docs/script.js | 教材のスタイルシートと、章ページの「この章の内容」を見出しから組み立てるスクリプト |
docs/*.png, docs/hayanagi-*.svg | 教材の図版と、ヘッダーなどで使うアイコン(assets/icon/ の写し) |
assets/icon/ | アイコン(SVG、16〜1024px の PNG、favicon.ico)。48px 以下は線を太くした hayanagi-icon-small.svg から書き出す |
assets/banner/ | README 冒頭のバナー。白地の hayanagi-banner と、GitHub のダークモードで使う背景透過の hayanagi-banner-dark(それぞれ文字をアウトライン化した SVG と 2 倍解像度の PNG) |
バージョンは src/version.h の HAYANAGI_VERSION が唯一の定義元で、CMake の project(... VERSION)、
USI の id name、--version はすべてここから読みます。リリース時はこの値と本節を更新し、
同じ番号のタグ(v1.5.1 など)を付けます。ShogiBoardQ はタグで指定した版をサブモジュールとして参照します。
| バージョン | タグ | 日付 | 概要 |
|---|---|---|---|
| 1.5.1 | v1.5.1 | 2026-10-04 | リソース解放漏れの修正、評価処理の分離、将棋エンジン解説教材の追加 |
| 1.5.0 | 単独リリースなし(1.5.1に収録) | 2026-10-01 | 独自定跡の生成・検証、通常探索・評価と定跡読込の改善、配布準備 |
| 1.4.0 | v1.4.0 | 2026-09-28 | 棋力制限・解析モード、コピー保護状態の通知 |
| 1.3.0 | v1.3.0 | 2026-09-28 | 初手制限・残り手数指定・デバッグ、追加探索情報と評価値の上下限通知 |
| 1.2.0 | v1.2.0 | 2026-09-28 | 標準詰将棋解答・詰みスコア、USI 互換性と探索終了処理の改善 |
| 1.1.0 | v1.1.0 | 2026-09-28 | 詰み確認・詰将棋・perft の並列化、ワーカー再利用、逐次処理の高速化 |
| 1.0.1 | v1.0.1 | 2026-09-25 | Clang での -Wsign-conversion 警告を解消(ShogiBoardQ が参照中) |
| 1.0.0 | v1.0.0 | 2026-09-25 | 詰み探索と局面処理の高速化、ベンチマーク、単体テスト、バージョン情報 |
1.5.0 の変更も含むリリースです。
src/evaluation.cpp に分離し、詰み探索と perft の重複処理を整理しました。hnakada123 に統一しました。docs/ に追加しました。no_book、終局条件、予想応手の合法性の扱いを改善しました。ビルド時に配置する定跡も選択できます。hayanagi_book.db に統一し、BookFile の選択候補を no_book と hayanagi_book.db に整理しました。USI_LimitStrength / USI_Strength による探索量の制限と、USI_AnalyseMode による解析用動作を追加しました。copyprotection checking / ok の通知に対応しました。利用者登録やコピー制限は追加していません。go depth N infinite でも指定した探索深さを維持するように修正しました。go searchmoves / movestogo と debug on/off に対応しました。info currmovenumber / cpuload / currline / refutation と、表示切り替えオプションを追加しました。lowerbound / upperbound を通知し、全窓で再探索して評価値を確定します。searchmoves と定跡・並列探索・MultiPV・中断・置換表再利用の整合性を検証するテストを追加しました。go mate / checkmate と score mate に対応し、入玉などの勝敗との区別を追加しました。USI_Hash と gameover に対応し、go infinite の返答待機、先読み終了時の結果出力を修正しました。seldepth / hashfull / currmove の通知、並列出力の排他処理、CRLF・空白付きパス対応を追加しました。position の後に以前の局面で通常探索してしまう問題を修正しました。Threads を通常探索前の詰み確認、go tsume / bench tsume、perft に適用しました。小さい探索は逐次処理し、詰み手数・玉方の最長抵抗・perft の統計と出力順を維持します。TsumeSearch::solve に省略可能な threads 引数を追加しました。既存の 5 引数呼び出しも利用でき、既定値は 1 です。-Wconversion が -Wsign-conversion を含むため、Qt Creator の Clang コードモデルが Hayanagi のソースに約 490 件の符号変換警告を報告していました(GCC でのビルドは元から警告なしで、ビルド失敗ではありません)。-Wno-sign-conversion を併記して GCC と同じ警告範囲にし、Clang 22 でも警告ゼロでビルドとテストが通ることを確認しています。探索や結果の変更はありません。最初の明示的なバージョンです。ShogiBoardQ が参照していたコミット 30cfce5 からの主な変更は次のとおりです。
make_move / unmake_move で探索し、置換表を深さごとの std::unordered_map から、詰み・不詰の証明を深さをまたいで再利用する固定サイズの表に置き換えました。5 手詰の局面で約 15〜18 倍、攻方の持駒が多い不詰局面(深さ 5)で約 24 倍速くなっています(BENCHMARK.md)。has_legal_move を追加し、perft も約 2 割速くなっています。perft の結果と通常探索のノード数は変わっていません。depthlimit だった局面で不詰の証明 nomate を返すことがあります。bench tsume、tests/bench_tsume.py、C++ 単体テスト hayanagi_tests を追加しました。-Wshadow -Wconversion を有効にしました。src/version.h、id name Hayanagi 1.0.0、--version)を追加しました。setoption name MaxMovesToDraw value Nsetoption name EnteringKingRule value <rule>(NoEnteringKing / CSARule24 / CSARule24H / CSARule27 / CSARule27H / TryRule)setoption name GenerateAllLegalMoves value <bool>setoption name TsumeMode value <bool>(片玉の局面を受け付ける)stopponderhitdebug on|off(診断情報の切り替え)gameover win|lose|draw(進行中の探索と先読みを終了)quitbench depth Nbench nodes Nbench current depth Nbench tsume [movetime M](詰み探索の固定局面ベンチマーク)perft Nperft depth N divide