サイドがチェックされているかどうかを判断するためのより効率的な方法があります。キングから外側にスキャンして、それを攻撃できるピースを見つけるかどうかを確認します。例えば、キングの位置から、敵のビショップが対角線に沿っているかどうかなどを確認します。移動リストを生成する必要はまったくないので、再帰は必要ありません。ここにいくつかの擬似コードがあります:
function leftInCheck(board, sideToCheck) {
// one of the four rays for bishop/queen attacks
d := 0
while (king rank + d, king file + d) is on the board
piece := board[king rank + d][king file + d]
if piece is an enemy bishop or queen
return true
if piece is not an empty square // a piece blocks any potential
break // attack behind it so we can stop
d := d + 1
// do this for all the other forms of attack
...
return false
}
ご覧のとおり、コードの繰り返しがありますが、短くすることができます。わかりやすいのでそのままにしておきました。今行っているように疑似合法的な動きを生成し、それぞれを作成し、上記のサブルーチンでチェックを残すものを省略することにより、正当な動きを生成できます。これには、当然のことながら、追加の利点があります。ここにいくつかの擬似コードがあります:
function legalMoves(board, sideToMove) {
moveList := empty
for each move in pseudoLegalMoves()
make(move)
if not leftInCheck(board, sideToMove)
moveList.add(move)
unmake(move) // you may not need this
return moveList
}
キャスリングでは、キングとルークの間のマスに攻撃があるかどうかを確認する必要があります。幸いなことに、上記のサブルーチンを拡張して、キング以外の正方形でも機能するようにすることができるので、これは簡単です。
ビットボードや 0x88 を使用しておらず、代わりに単純な配列表現を使用していると思います。これにより、固定されたピースを決定するために攻撃マップを非常に高速に生成する必要があるため、合法的な動きの生成を実装することが少し難しくなります (中間の疑似合法的な動きはありません)。あなたが野心的であれば、これは可能性です。
追加の注意として、ここでの他の回答には少しがっかりしています。また、優れたムーブジェネレーターを作成したい人には、私自身の回答をお勧めしません (チェスのプログラミングに不慣れな人のみを対象としています)。これは、徹底的に検討され、よく知られた解決策があるトピックですが、独創的なアイデアを引き出しています。もちろん、これには何も問題はありませんが、なぜ車輪を再発明する必要があるのでしょうか。ムーブ生成の確立された方法を調べてください。