# 千日手と反復局面
反復局面(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/)