国际象棋程序设计(无AI) - 移动验证 [英] Chess programming (no AI) - moves validation

查看:154
本文介绍了国际象棋程序设计(无AI) - 移动验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想编程我自己的国际象棋引擎(无AI)。
我知道有棋入门套件,我看着它启动灵感。

I'm trying to program my own chess engine (no AI). I know there is Chess Game Starter Kit and I watched it for start inspiration.

但我没听清是被验证,其中移动(的这里是我的非王件的动作验证)防止让自己检查

But what I didn't catch is where are validated moves (here is moves validation) for my non-king pieces preventing to get myself to check?

想象一下情况:

A5 - 对手鲁克结果
A4 - 我的主教结果
A3 - 我的国王

Imagine situation:
A5 - opponents rook
A4 - my bishop
A3 - my king

我不能现在把我的主教,因为我会得到检查。

I can't move my bishop now since I would get to check.

还是建议你将如何检查这种情况呢?

Or how would you suggest to check this situation?

谢谢

推荐答案

对于一个给定板位置,大多数的国际象棋引擎通过生成唯一的伪合法移动启动。通过假冒合法,我的意思是一招将生成即使它:

For a given board position, most chess engines start by generating pseudo-legal moves only. By pseudo-legal, I mean a move will be generated even if it:


  • 叶在检查金

  • 将景成检查

  • 横跨正方形城堡正在攻击

这样做的原因是性能。由于许多动作实际上不会被搜索由于β修剪,你避免招有效性的全面检查节约时间。

The reason for this is performance. As many moves won't actually be searched due to beta pruning, you save time by avoiding the full check of move validity.

对于每个此举是的搜索,你需要检查它确实是有效的。这通常是通过将国王的颜色和方(和广场旁的国王为王车易位移动)到的 IsAttacked 的方法来完成。如果该方法返回true,你知道此举是不是有效的,因此,你不应该包括在你的搜索。

For every move that is searched, you need to check that it's really valid. This is normally done by passing the King's colour and square (and squares next to the King for a castling move) into an IsAttacked method. If that method returns true, you know the move isn't valid and therefore you shouldn't include it in your search.

这是 IsAttacked 从我自己的C#国际象棋引擎的方法。请记住,我的引擎魔力棋盘为基础,所以代码将无法直接适用以国际象棋入门工具包您联系。除非你熟悉的魔法位棋盘,翻译不会是微不足道的。

This is the IsAttacked method from my own C# chess engine. Bear in mind that my engine is magic bitboard-based, so the code won't be directly applicable to the chess starter kit to which you linked. Unless you're familiar with magic bitboards, the translation won't be trivial.

// IsAttacked is primarily used as a move legality test to see if a set of 
// one or more squares is under attack from the side to move.
// It returns true as soon as an attack is detected, otherwise returns false.
// It can be used for check detection, castling legality, or simply to 
// detect whether a specific square is attacked.
internal bool IsAttacked(Board board, UInt64 targetSquares, bool whiteAttacking)
{
    UInt64 slidingAttackers; Int32 targetSquare;
    UInt64 remainingTargetSquares = targetSquares;

    // Test for attacks by WHITE on any of the target squares.
    if (whiteAttacking) 
    {
        // For the remaining target squares...
        while (remainingTargetSquares != 0)
        {
            // Find the next square in the list.
            targetSquare = BitOperations.BitScanForward(remainingTargetSquares);

            // Is this square attacked by a pawn, knight, or king?
            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;

            // Is this square attacked by a queen or rook along a file or rank?
            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;
            }

            // Is this square attacked by a queen or bishop along a diagonal?
            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;
            }

            // This square isn't attacked - remove and move on to next target square.
            remainingTargetSquares ^= Constants.BITSET[targetSquare];
        }
    }

    // Test for attacks by BLACK on any of the target squares.
    else
    {
        // For the remaining target squares...
        while (remainingTargetSquares != 0)
        {
            // Find the next square in the list.
            targetSquare = BitOperations.BitScanForward(remainingTargetSquares);

            // Is this square attacked by a pawn, knight, or king?
            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;

            // Is this square attacked by a queen or rook along a file or rank?
            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;
            }

            // Is this square attacked by a queen or bishop along a diagonal?
            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;
            }

            // This square isn't attacked - remove and move on to next target square.
            remainingTargetSquares ^= Constants.BITSET[targetSquare];
        }
    }

    // None of the target squares are attacked.
    return false;
}



下面是白生成伪法律易位移动的代码片段:

Here's a fragment of code that generates pseudo-legal castling moves for White:

// If White can still castle kingside...
if ((board.WhiteCastlingStatus & Board.EnumCastlingStatus.CanCastleOO) != 0)
{
    // And the White kingside castling squares (F1/G1) aren't occupied...
    if ((Constants.MASK_FG[Constants.WHITE_MOVE] & board.OccupiedSquares) == 0)
    {
        board.MoveBuffer[moveIndex++] = Constants.WHITE_CASTLING_OO;
    }
}

// If White can still castle queenside...
if ((board.WhiteCastlingStatus & Board.EnumCastlingStatus.CanCastleOOO) != 0)
{
    // And the White queenside castling squares (D1/C1/B1) aren't occupied...
    if ((Constants.MASK_BD[Constants.WHITE_MOVE] & board.OccupiedSquares) == 0)
    {
        board.MoveBuffer[moveIndex++] = Constants.WHITE_CASTLING_OOO;
    }
}

和这里的,检查是否假冒合法的代码王车易位的举动实际上是合法的:

And here's the code that checks whether a pseudo-legal castling move is actually legal:

// Checks whether the King is moving from or into check.
// Checks whether the King is moving across attacked squares.
internal bool IsCastlingMoveLegal(Board board, Move move)
{
    if (move.IsCastlingOO)
    {
        if (move.IsWhiteMove)
        {
            // Are any of the White kingside castling squares (E1/F1/G1) attacked?
            return !this.IsAttacked(board, Constants.MASK_EG[Constants.WHITE_MOVE], false);
        }
        else
        {
            // Are any of the Black kingside castling squares (E8/F8/G8) attacked?
            return !this.IsAttacked(board, Constants.MASK_EG[Constants.BLACK_MOVE], true);
        }
    }
    else if (move.IsCastlingOOO)
    {
        if (move.IsWhiteMove)
        {
            // Are any of the White queenside castling squares (E1/D1/C1) attacked?
            return !this.IsAttacked(board, Constants.MASK_CE[Constants.WHITE_MOVE], false);
        }
        else
        {
            // Are any of the Black queenside castling squares (E8/D8/C8) attacked?
            return !this.IsAttacked(board, Constants.MASK_CE[Constants.BLACK_MOVE], true);
        }
    }
    // Not a castling move!
    else
    {
        Debug.Assert(false, "Not a castling move!");
        return true;
    }
}

这篇关于国际象棋程序设计(无AI) - 移动验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆