对于给定的棋盘位置,大多数国际象棋引擎都会从生成伪合法着手。所谓伪合法,是指即使走法:
- 将国王置于被将军状态
- 将国王移动到被将军状态
- 在正在受到攻击的方格上进行王车易位
也会生成。
这样做的原因是为了提高性能。由于许多走法实际上不会被搜索到(由于贝塔剪枝),通过避免完全检查走法的有效性,可以节省时间。
对于每个被搜索的走法,您需要检查它是否真正有效。通常,这是通过将国王的颜色和位置(以及王车易位的情况下国王旁边的方格)传递到一个IsAttacked方法中来完成的。如果该方法返回true,则表示该走法无效,因此您不应将其包含在搜索中。
以下是我自己的C#国际象棋引擎中的IsAttacked方法。请注意,我的引擎基于
魔术位板,因此该代码不会直接适用于您链接的国际象棋入门套件。除非您熟悉魔术位板,否则翻译将不是一件简单的事情。
internal bool IsAttacked(Board board, UInt64 targetSquares, bool whiteAttacking)
{
UInt64 slidingAttackers; Int32 targetSquare;
UInt64 remainingTargetSquares = targetSquares;
if (whiteAttacking)
{
while (remainingTargetSquares != 0)
{
targetSquare = BitOperations.BitScanForward(remainingTargetSquares);
if ((board.WhitePawns & Constants.BLACK_PAWN_ATTACKS[targetSquare]) != 0) return true;
if ((board.WhiteKnights & Constants.KNIGHT_ATTACKS[targetSquare]) != 0) return true;
if ((board.WhiteKing & Constants.KING_ATTACKS[targetSquare]) != 0) return true;
slidingAttackers = board.WhiteQueens | board.WhiteRooks;
if (slidingAttackers != 0)
{
if (this.RankMoves(board.OccupiedSquares, slidingAttackers, targetSquare) != 0) return true;
if (this.FileMoves(board.OccupiedSquares, slidingAttackers, targetSquare) != 0) return true;
}
slidingAttackers = board.WhiteQueens | board.WhiteBishops;
if (slidingAttackers != 0)
{
if (this.DiagonalA8H1Moves(board.OccupiedSquares, slidingAttackers, targetSquare) != 0) return true;
if (this.DiagonalA1H8Moves(board.OccupiedSquares, slidingAttackers, targetSquare) != 0) return true;
}
remainingTargetSquares ^= Constants.BITSET[targetSquare];
}
}
else
{
while (remainingTargetSquares != 0)
{
targetSquare = BitOperations.BitScanForward(remainingTargetSquares);
if ((board.BlackPawns & Constants.WHITE_PAWN_ATTACKS[targetSquare]) != 0) return true;
if ((board.BlackKnights & Constants.KNIGHT_ATTACKS[targetSquare]) != 0) return true;
if ((board.BlackKing & Constants.KING_ATTACKS[targetSquare]) != 0) return true;
slidingAttackers = board.BlackQueens | board.BlackRooks;
if (slidingAttackers != 0)
{
if (this.RankMoves(board.OccupiedSquares, slidingAttackers, targetSquare) != 0) return true;
if (this.FileMoves(board.OccupiedSquares, slidingAttackers, targetSquare) != 0) return true;
}
slidingAttackers = board.BlackQueens | board.BlackBishops;
if (slidingAttackers != 0)
{
if (this.DiagonalA8H1Moves(board.OccupiedSquares, slidingAttackers, targetSquare) != 0) return true;
if (this.DiagonalA1H8Moves(board.OccupiedSquares, slidingAttackers, targetSquare) != 0) return true;
}
remainingTargetSquares ^= Constants.BITSET[targetSquare];
}
}
return false;
}
这是一段生成白方伪合法王车易位走法的代码片段:
if ((board.WhiteCastlingStatus & Board.EnumCastlingStatus.CanCastleOO) != 0)
{
if ((Constants.MASK_FG[Constants.WHITE_MOVE] & board.OccupiedSquares) == 0)
{
board.MoveBuffer[moveIndex++] = Constants.WHITE_CASTLING_OO;
}
}
if ((board.WhiteCastlingStatus & Board.EnumCastlingStatus.CanCastleOOO) != 0)
{
if ((Constants.MASK_BD[Constants.WHITE_MOVE] & board.OccupiedSquares) == 0)
{
board.MoveBuffer[moveIndex++] = Constants.WHITE_CASTLING_OOO;
}
}
这里是检查伪装合法的王车易位是否真正合法的代码:
internal bool IsCastlingMoveLegal(Board board, Move move)
{
if (move.IsCastlingOO)
{
if (move.IsWhiteMove)
{
return !this.IsAttacked(board, Constants.MASK_EG[Constants.WHITE_MOVE], false);
}
else
{
return !this.IsAttacked(board, Constants.MASK_EG[Constants.BLACK_MOVE], true);
}
}
else if (move.IsCastlingOOO)
{
if (move.IsWhiteMove)
{
return !this.IsAttacked(board, Constants.MASK_CE[Constants.WHITE_MOVE], false);
}
else
{
return !this.IsAttacked(board, Constants.MASK_CE[Constants.BLACK_MOVE], true);
}
}
else
{
Debug.Assert(false, "Not a castling move!");
return true;
}
}