Шахматное программирование (без ИИ) - проверка ходов

Я пытаюсь запрограммировать свой собственный шахматный движок (без ИИ). Я знаю, что существует Стартовый набор для игры в шахматы, и я смотрел его для вдохновения.

Но чего я не уловил, так это того, где проверенные ходы (здесь проверка ходов) за то, что мои фигуры, не являющиеся королем, мешают мне заставить себя проверить?

Представьте ситуацию:
A5 - ладья противника
A4 - мой слон
A3 - мой король

Сейчас я не могу ходить своим слоном, потому что мне придется сделать чек.

Или как бы вы предложили проверить эту ситуацию?

Спасибо


person o..o    schedule 25.08.2011    source источник
comment
Вы имеете в виду, как вы подтверждаете, что ход является незаконным, потому что при этом он ставит вас под шах?   -  person Kevin    schedule 26.08.2011
comment
О, вы имеете в виду, что хотите выяснить, где связанный код выполняет такую ​​проверку?   -  person AakashM    schedule 26.08.2011
comment
Да, поскольку я читал связанный код, я не понял, что это будет решено где угодно.   -  person o..o    schedule 26.08.2011
comment
ваша ссылка, похоже, указывает на страницу с общей информацией, а не на описание проверки перемещения.   -  person Kevin    schedule 26.08.2011
comment
Хорошо, я понял, что вы имеете в виду. Итак, вы действительно проверили это? Действительно ли этот класс позволял вам поставить своего короля под открытый шах?   -  person Konrad Morawski    schedule 26.08.2011
comment
Проверка ходов находится здесь: chessbin.com/post/Chess-Piece-Valid -Moves.aspx Нет, не проверял. Мне интересно, как это сделать, поэтому я хотел вдохновить себя, но я вообще не нашел его в их коде. Во всяком случае - есть некоторые передовые подходы?   -  person o..o    schedule 26.08.2011
comment
@o..o эта ссылка перенаправляет на домашнюю страницу   -  person Ben Robinson    schedule 26.08.2011
comment
Извините ребята, опечатка. Теперь ссылки правильные.   -  person o..o    schedule 26.08.2011
comment
это какой-то уродливый код, с которого вы начинаете.   -  person Kevin    schedule 26.08.2011
comment
Лучший способ описать позицию на доске — использовать FEN. PGN также является обязательным. Я скачал Chess Game Starter Kit, чтобы иметь о нем мнение. Поделитесь своими выводами или уточните свой вопрос, чтобы не останавливаться на достигнутом.   -  person menjaraz    schedule 10.12.2011


Ответы (2)


Для данной позиции на доске большинство шахматных движков начинают с генерации только псевдоправильных ходов. Под псевдолегальным я подразумеваю, что ход будет сгенерирован, даже если он:

  • Оставляет короля под шахом
  • Ставит короля под шах
  • Замки на площадях, на которые нападают

Причиной этого является производительность. Поскольку многие ходы на самом деле не будут искаться из-за бета-сокращения, вы экономите время, избегая полной проверки правильности ходов.

Для каждого хода, который искомый ищется, вам нужно убедиться, что он действительно действителен. Обычно это делается путем передачи цвета и клетки короля (и клеток рядом с королем для рокировки) в метод IsAttacked. Если этот метод возвращает значение true, вы знаете, что перемещение недопустимо, и поэтому вам не следует включать его в поиск.

Это метод IsAttacked из моего собственного шахматного движка C#. Имейте в виду, что мой движок основан на magic Bitboard, поэтому код не будет напрямую применим к шахматный стартовый комплект, на который вы ссылались. Если вы не знакомы с волшебными битбордами, перевод не будет тривиальным.

// 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;
}

Вот фрагмент кода, генерирующий псевдолегальные рокировки за белых:

// 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;
    }
}

А вот код, который проверяет, действительно ли допустима псевдолегальная рокировка:

// 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;
    }
}
person HTTP 410    schedule 21.12.2011

В моей шахматной программе есть метод, который проверяет, угрожает ли поле. При расчете ходов короля проверяется каждое поле, на которое король может переместиться, если этому полю угрожает опасность.

person MrFox    schedule 22.09.2012