# 千日手と反復局面

反復局面(Repetitions)は、探索中に同じ局面が繰り返し現れる現象である。
将棋では特に千日手判定に直結するため、探索実装で重要である。

## 概要

探索では、手順を進めていくうちに以前と同じ局面へ戻ることがある。
このとき、

- 盤面配置
- 手番
- 持ち駒

が同じなら、将棋では同一局面として扱う。

探索器はこれを検出して、

- 千日手
- 連続王手の千日手
- 引き分け相当の扱い

などを判断する必要がある。

## どう検出するか

典型的には、手順履歴に沿って[ゾブリストハッシュ](/shogi/shogiwiki/search/zobrist-hashing/)のキーを並べておき、
同じキーが過去に出てきたかを確認する。

```cpp
bool isRepetition(const std::vector<uint64_t>& history, uint64_t currentKey) {
    for (int i = (int)history.size() - 4; i >= 0; i -= 2) {
        if (history[i] == currentKey) {
            return true;
        }
    }
    return false;
}
```

同じ手番で比較するため、2 手ずつさかのぼる形が使われることが多い。

## 将棋特有の注意点

チェスでは三fold repetition だが、将棋では千日手の扱いが異なる。
特に重要なのは、

- 連続王手の千日手
- 持将棋
- ルールセット差

である。

そのため、単に「同じ局面が出たら引き分け値」とするだけでは不十分で、
将棋ルールに合わせた判定が必要になる。

## 探索上の扱い

反復局面を検出したら、

- 引き分け値
- やや文脈付きの値
- 連続王手なら負け相当

などを返す実装が考えられる。

ここは GUI や大会ルールとの整合も重要である。

## 将棋AIでの位置づけ

将棋では、受けを続けると同じ局面へ戻ることが比較的起こりやすい。
また、詰み回避や王手ラッシュの探索では、反復検出がないと無限ループ的な挙動になりやすい。

そのため、

- [ゾブリストハッシュ](/shogi/shogiwiki/search/zobrist-hashing/)
- 履歴管理
- 王手判定

を組み合わせた実装が重要である。

## 注意点

- キー衝突は理論上ありうるので、完全一致判定には注意が必要
- 連続王手の千日手は通常の千日手と同じ扱いではない
- ルール差がある環境では値の返し方を調整する必要がある

## 関連項目

- [ゾブリストハッシュ](/shogi/shogiwiki/search/zobrist-hashing/)
- [置換表](/shogi/shogiwiki/search/transposition-table/)
- [探索](/shogi/shogiwiki/search/)

## 参考にしたホームページ

- [Chessprogramming Wiki: Repetitions](https://www.chessprogramming.org/Repetitions)
- [Chessprogramming Wiki: Reversible Moves](https://www.chessprogramming.org/Reversible_Moves)
- [www.shogi.or.jp: RULE](https://www.shogi.or.jp/faq/rule/)