基本型
前提知識: 内部技術ドキュメントの概要
このページの要点
- rsshogi は座標・駒・指し手を newtype パターン で独自に定義し、コンパイル時に誤用を防ぐ
- 各型の数値インデックスは 互換 であり、他エンジンの知見やデバッグ情報がそのまま使える
- すべての型は ゼロコスト抽象 で、実行時のオーバーヘッドはない(内部は
i8、Moveのみu16) - 機械学習向けの move label は
labels::policyとして独立モジュールに切り出し、Move/Colorから純粋変換できる
なぜ独自の型が必要か
将棋ライブラリでは、座標・駒・指し手を数値インデックスとして表現することで、以下を実現しています。
- ビットボードとの整合: 縦型レイアウトが香・歩の利き計算を最適化
- 合法手生成の高速化: ビットフラグによる成り判定・先後判定が 1 命令で完了
- エンジン互換性: 主要な将棋エンジンの主要エンジンと互換性のある設計
- SFEN/USI 互換: 標準的な棋譜表記との相互変換が容易
もし型がなかったら
型を使わず生の u8 だけで書いたコードを考えてみましょう。
fn do_move(board: &mut [u8; 81], from: u8, to: u8, piece: u8) {
board[to as usize] = piece;
board[from as usize] = 0;
}
// 以下のコードはコンパイルが通るが、意味的にはバグ
do_move(&mut board, piece, to, from); // piece と from を入れ違えた!
Square, Piece, Move を使えば、引数の取り違えはコンパイルエラーになります。
Rust の型システムが「間違った組み合わせ」を実行前に検出してくれるのです。
設計哲学
rsshogi の型設計は 3 つの原則に従っています。
| 原則 | 内容 | 例 |
|---|---|---|
| Newtype | 同じ i8 でも Square と PieceType は別の型 | Square(40) を PieceType に渡せない |
| ゼロコスト | newtype は実行時に消え、生の整数演算と同じ機械語になる | Square(a) + 1 → add al, 1 |
| 互換 | インデックス体系を合わせ、デバッグ時に値を直接比較できる | PAWN = 1, SQ_55 = 40 |
この章の構成
座標系
将棋盤の 81 マスをどのように数値化するかを解説します。
- Square(マス): 0-80 のインデックス表現
- 座標計算式:
square_index = file * 9 + rank - 方角定数: 駒の移動方向(上下左右、斜め)
駒
駒をどのようにエンコードするかを解説します。
- PieceType: 駒種(0-15、歩〜龍)
- Piece: 駒+先後(0-31)
- 成り変換: +8 オフセットによる成駒表現
- ビットフラグ構造: 先後・成り・駒種の効率的なエンコーディング
指し手
指し手をどのようにエンコードするかを解説します。
- Move: 16 ビットのコンパクト表現
- Move32: 32 ビットの完全表現
- USI/CSA/KI2 表記: 各フォーマットとの相互変換
Policy ラベル
学習用の move label scheme をどのように core に載せるかを解説します。
- MoveLabel: 27x81 = 2187 クラスの policy ラベル
- CompactMoveLabel: 構造的に現れうる 1496 クラスへの圧縮
- scope: 局面やテンソル表現に依存しない純粋変換だけを
rsshogi::labels::policyで提供
読了順序
座標 → 駒 → 指し手 の順に読むことを推奨します。 各ページで導入される概念は後続のページで使用されます。
次に読む
→ 座標系: 81 マスの数値化と、将棋特有の「縦型」レイアウトの理由から始めます。