コード例 #1
0
    protected override void ComputeMoves()
    {
        // Compute universal moves for rooks
        this.moves = new Dictionary <Position, Bitboard>();

        int column, row;

        for (column = Position.min; column <= Position.max; column++)
        {
            for (row = Position.min; row <= Position.max; row++)
            {
                Position position         = new Position(column, row);
                Bitboard positionBitboard = new Bitboard();

                int positionRow, positionColumn;
                for (positionColumn = Position.min; positionColumn <= Position.max; positionColumn++)
                {
                    if (positionColumn != column)
                    {
                        positionBitboard.FlipPosition(new Position(positionColumn, row));
                    }
                }
                for (positionRow = Position.min; positionRow <= Position.max; positionRow++)
                {
                    if (positionRow != row)
                    {
                        positionBitboard.FlipPosition(new Position(column, positionRow));
                    }
                }

                this.moves[position] = positionBitboard;
            }
        }
    }
コード例 #2
0
    protected override Bitboard AdditionalMoveProcessing(Bitboard movesForCurrentPosition)
    {
        if (this.side == Side.Black)
        {
            movesForCurrentPosition = movesForCurrentPosition.ComputeRayIntersections(this.chessBoard.GetPieceLocations(Side.White), this.GetCurrentPosition(), true);
        }
        else
        {
            movesForCurrentPosition = movesForCurrentPosition.ComputeRayIntersections(this.chessBoard.GetPieceLocations(Side.Black), this.GetCurrentPosition(), true);
        }
        movesForCurrentPosition = movesForCurrentPosition.ComputeRayIntersections(this.chessBoard.GetPieceLocations(this.side), this.GetCurrentPosition(), false);

        // The current moving side check is needed since we don't want to compute castling as a move when we're trying to see if the king is checked
        // Castling
        if (this.chessBoard.CurrentMovingSide() == this.side &&
            this.canCastle &&
            !this.chessBoard.IsKingInCheck(this.side)
            )
        {
            // King side castling
            if (this.chessBoard.GetPieceAtPosition(new Position(1, this.GetCurrentPosition().GetRow())) != null &&
                this.chessBoard.GetPieceAtPosition(new Position(1, this.GetCurrentPosition().GetRow())).GetType().Name == Constants.PieceClassNames.Rook)
            {
                Rook kingSideRook = (Rook)this.chessBoard.GetPieceAtPosition(new Position(1, this.GetCurrentPosition().GetRow()));
                // If both move positions are unoccupied
                if (kingSideRook.canCastle &&
                    this.chessBoard.GetPieceAtPosition(new Position(2, this.GetCurrentPosition().GetRow())) == null &&
                    this.chessBoard.GetPieceAtPosition(new Position(3, this.GetCurrentPosition().GetRow())) == null
                    )
                {
                    // The final move will be filtered if the King's target position leaves it in check, so the last check here should be the intermediate position, or where the Rook will be after the move
                    if (this.IsMoveSafe(new Position(3, this.GetCurrentPosition().GetRow())))
                    {
                        movesForCurrentPosition.FlipPosition(new Position(2, this.GetCurrentPosition().GetRow()));
                    }
                }
            }

            // Queen side castling
            if (this.chessBoard.GetPieceAtPosition(new Position(8, this.GetCurrentPosition().GetRow())) != null &&
                this.chessBoard.GetPieceAtPosition(new Position(8, this.GetCurrentPosition().GetRow())).GetType().Name == Constants.PieceClassNames.Rook)
            {
                Rook queenSideRook = (Rook)this.chessBoard.GetPieceAtPosition(new Position(8, this.GetCurrentPosition().GetRow()));
                if (queenSideRook.canCastle &&
                    this.chessBoard.GetPieceAtPosition(new Position(5, this.GetCurrentPosition().GetRow())) == null &&
                    this.chessBoard.GetPieceAtPosition(new Position(6, this.GetCurrentPosition().GetRow())) == null
                    )
                {
                    // The final move will be filtered if the King's target position leaves it in check, so the last check here should be the intermediate position, or where the Rook will be after the move
                    if (this.IsMoveSafe(new Position(5, this.GetCurrentPosition().GetRow())))
                    {
                        movesForCurrentPosition.FlipPosition(new Position(6, this.GetCurrentPosition().GetRow()));
                    }
                }
            }
        }

        return(movesForCurrentPosition);
    }
コード例 #3
0
    protected override void ComputeMoves()
    {
        // Compute moves based on side for pawns
        this.moves = new Dictionary <Position, Bitboard>();
        int row, column;

        if (this.side == Side.Black)
        {
            // Starting position
            row = 7;
            for (column = Position.min; column <= Position.max; column++)
            {
                Position position         = new Position(column, row);
                Bitboard positionBitboard = new Bitboard();
                positionBitboard.FlipPosition(new Position(column, row - 1));
                positionBitboard.FlipPosition(new Position(column, row - 2));
                this.moves[position] = positionBitboard;
            }

            // All other forward positions (till pawn promotion)
            for (row = 6; row >= 2; row--)
            {
                for (column = Position.min; column <= Position.max; column++)
                {
                    Position position         = new Position(column, row);
                    Bitboard positionBitboard = new Bitboard();
                    positionBitboard.FlipPosition(new Position(column, row - 1));
                    this.moves[position] = positionBitboard;
                }
            }
        }
        else
        {
            // Starting position
            row = 2;
            for (column = Position.min; column <= Position.max; column++)
            {
                Position position         = new Position(column, row);
                Bitboard positionBitboard = new Bitboard();
                positionBitboard.FlipPosition(new Position(column, row + 1));
                positionBitboard.FlipPosition(new Position(column, row + 2));
                this.moves[position] = positionBitboard;
            }

            // All other forward positions (till pawn promotion)
            for (row = 3; row <= 7; row++)
            {
                for (column = Position.min; column <= Position.max; column++)
                {
                    Position position         = new Position(column, row);
                    Bitboard positionBitboard = new Bitboard();
                    positionBitboard.FlipPosition(new Position(column, row + 1));
                    this.moves[position] = positionBitboard;
                }
            }
        }
    }
コード例 #4
0
    protected override void ComputeMoves()
    {
        // Compute universal moves for bishops
        this.moves = new Dictionary <Position, Bitboard>();

        int column, row;

        for (column = Position.min; column <= Position.max; column++)
        {
            for (row = Position.min; row <= Position.max; row++)
            {
                Position position         = new Position(column, row);
                Bitboard positionBitboard = new Bitboard();

                int positionRow, positionColumn;

                for (positionColumn = column + 1;
                     positionColumn <= Position.max;
                     positionColumn++)
                {
                    positionRow = row + (positionColumn - column);
                    if (positionRow <= Position.max)
                    {
                        positionBitboard.FlipPosition(new Position(positionColumn, positionRow));
                    }

                    positionRow = row - (positionColumn - column);
                    if (positionRow >= Position.min)
                    {
                        positionBitboard.FlipPosition(new Position(positionColumn, positionRow));
                    }
                }

                for (positionColumn = column - 1;
                     positionColumn >= Position.min;
                     positionColumn--)
                {
                    positionRow = row + (column - positionColumn);
                    if (positionRow <= Position.max)
                    {
                        positionBitboard.FlipPosition(new Position(positionColumn, positionRow));
                    }

                    positionRow = row - (column - positionColumn);
                    if (positionRow >= Position.min)
                    {
                        positionBitboard.FlipPosition(new Position(positionColumn, positionRow));
                    }
                }

                this.moves[position] = positionBitboard;
            }
        }
    }
コード例 #5
0
    public Bitboard ComputeRayIntersections(Bitboard bitboardToIntersect, Position movingPiecePosition, bool includeIntersectionPosition)
    {
        // Recompute this bitboard after stopping all rays from the moving piece that are intersecting the passed bitboard
        Bitboard newBitboard = new Bitboard();
        // Compute a bitboard containing all intersection points
        Bitboard intersectBitboard = this.ComplementBitboard(this.IntersectBitboard(bitboardToIntersect));
        int      row;

        for (row = 0; row < this.bitboard.Length; row++)
        {
            newBitboard.GetBitboard()[row]       = (byte)this.GetBitboard()[row];
            intersectBitboard.GetBitboard()[row] = (byte)(intersectBitboard.GetBitboard()[row] & newBitboard.GetBitboard()[row]);
        }

        // Now, for each intersect position, go along the unit vector connecting the moving position to this position and wipe out all points till the edge of the bitboard
        // These "vectors" can only be horizontal, vertical or diagonal
        foreach (Position intersectionPosition in intersectBitboard.GetPositions())
        {
            Vector2 positionVector = new Vector2(intersectionPosition.GetColumn() - movingPiecePosition.GetColumn(),
                                                 intersectionPosition.GetRow() - movingPiecePosition.GetRow());
            if (positionVector.x > 1 || positionVector.x < -1)
            {
                positionVector.x = positionVector.x / Mathf.Abs(positionVector.x);
            }
            if (positionVector.y > 1 || positionVector.y < -1)
            {
                positionVector.y = positionVector.y / Mathf.Abs(positionVector.y);
            }

            Position clearPosition = new Position(intersectionPosition.GetColumn(), intersectionPosition.GetRow());
            if (includeIntersectionPosition)
            {
                // Don't process the intersection position
                clearPosition.SetColumn(clearPosition.GetColumn() + (int)positionVector.x);
                clearPosition.SetRow(clearPosition.GetRow() + (int)positionVector.y);
            }

            while (clearPosition.GetColumn() >= Position.min && clearPosition.GetColumn() <= Position.max &&
                   clearPosition.GetRow() >= Position.min && clearPosition.GetRow() <= Position.max)
            {
                if (newBitboard.ValueAtPosition(clearPosition) > 0)
                {
                    newBitboard.FlipPosition(clearPosition);
                }
                else
                {
                    break;
                }
                clearPosition.SetColumn(clearPosition.GetColumn() + (int)positionVector.x);
                clearPosition.SetRow(clearPosition.GetRow() + (int)positionVector.y);
            }
        }

        return(newBitboard);
    }
コード例 #6
0
    public Bitboard GetSafeMovesForCurrentPosition()
    {
        Bitboard availableMoves = this.GetMovesForCurrentPosition();

        foreach (Position position in availableMoves.GetPositions())
        {
            if (!IsMoveSafe(position))
            {
                availableMoves.FlipPosition(position);
            }
        }
        return(availableMoves);
    }
コード例 #7
0
    protected override void ComputeMoves()
    {
        // Compute universal moves for knights
        this.moves = new Dictionary <Position, Bitboard>();

        int column, row;

        for (column = Position.min; column <= Position.max; column++)
        {
            for (row = Position.min; row <= Position.max; row++)
            {
                Position position         = new Position(column, row);
                Bitboard positionBitboard = new Bitboard();

                List <Position> knightPositions = new List <Position>();
                knightPositions.Add(new Position(column + 2, row + 1));
                knightPositions.Add(new Position(column + 2, row - 1));
                knightPositions.Add(new Position(column - 2, row + 1));
                knightPositions.Add(new Position(column - 2, row - 1));
                knightPositions.Add(new Position(column + 1, row + 2));
                knightPositions.Add(new Position(column + 1, row - 2));
                knightPositions.Add(new Position(column - 1, row + 2));
                knightPositions.Add(new Position(column - 1, row - 2));

                foreach (Position knightPosition in knightPositions)
                {
                    if (knightPosition.GetColumn() >= Position.min && knightPosition.GetColumn() <= Position.max &&
                        knightPosition.GetRow() >= Position.min && knightPosition.GetRow() <= Position.max)
                    {
                        positionBitboard.FlipPosition(knightPosition);
                    }
                }

                this.moves[position] = positionBitboard;
            }
        }
    }
コード例 #8
0
    protected override Bitboard AdditionalMoveProcessing(Bitboard movesForCurrentPosition)
    {
        // For pawns, extra moves would constitute:
        // 1. Normal attack
        // 2. En passant

        // Normal attack
        // Check the row ahead for opponent locations
        int  rowToCheck;
        Side sideToCheck;

        if (this.side == Side.Black)
        {
            rowToCheck  = this.GetCurrentPosition().GetRow() - 1;
            sideToCheck = Side.White;
        }
        else
        {
            rowToCheck  = this.GetCurrentPosition().GetRow() + 1;
            sideToCheck = Side.Black;
        }

        Bitboard friendlyLocations = this.chessBoard.GetPieceLocations(this.side);
        Bitboard opponentLocations = this.chessBoard.GetPieceLocations(sideToCheck);

        // First, remove any moves that go through friendly or opponent
        movesForCurrentPosition = movesForCurrentPosition.ComputeRayIntersections(friendlyLocations, this.GetCurrentPosition(), false);
        movesForCurrentPosition = movesForCurrentPosition.ComputeRayIntersections(opponentLocations, this.GetCurrentPosition(), false);

        if (this.GetCurrentPosition().GetColumn() > Position.min)
        {
            if (opponentLocations.ValueAtPosition(new Position(this.GetCurrentPosition().GetColumn() - 1, rowToCheck)) > 0)
            {
                movesForCurrentPosition.FlipPosition(new Position(this.GetCurrentPosition().GetColumn() - 1, rowToCheck));
            }
        }
        if (this.GetCurrentPosition().GetColumn() < Position.max)
        {
            if (opponentLocations.ValueAtPosition(new Position(this.GetCurrentPosition().GetColumn() + 1, rowToCheck)) > 0)
            {
                movesForCurrentPosition.FlipPosition(new Position(this.GetCurrentPosition().GetColumn() + 1, rowToCheck));
            }
        }

        // En passant
        rowToCheck = this.GetCurrentPosition().GetRow();

        if (this.GetCurrentPosition().GetColumn() > Position.min)
        {
            if (opponentLocations.ValueAtPosition(new Position(this.GetCurrentPosition().GetColumn() - 1, rowToCheck)) > 0)
            {
                // Also check if the piece at this location is a pawn which has just performed a double jump
                AbstractPiece passedPiece = this.chessBoard.GetPieceAtPosition(new Position(this.GetCurrentPosition().GetColumn() - 1, rowToCheck));
                if (passedPiece != null && passedPiece.GetType().Name.CompareTo(this.GetType().Name) == 0 && ((Pawn)passedPiece).allowEnPassantCapture)
                {
                    int attackPoint = rowToCheck;
                    if (this.side == Side.Black)
                    {
                        attackPoint--;
                    }
                    else
                    {
                        attackPoint++;
                    }
                    movesForCurrentPosition.FlipPosition(new Position(this.GetCurrentPosition().GetColumn() - 1, attackPoint));
                }
            }
        }
        if (this.GetCurrentPosition().GetColumn() < Position.max)
        {
            if (opponentLocations.ValueAtPosition(new Position(this.GetCurrentPosition().GetColumn() + 1, rowToCheck)) > 0)
            {
                AbstractPiece passedPiece = this.chessBoard.GetPieceAtPosition(new Position(this.GetCurrentPosition().GetColumn() + 1, rowToCheck));
                if (passedPiece != null && passedPiece.GetType().Name.CompareTo(this.GetType().Name) == 0 && ((Pawn)passedPiece).allowEnPassantCapture)
                {
                    int attackPoint = rowToCheck;
                    if (this.side == Side.Black)
                    {
                        attackPoint--;
                    }
                    else
                    {
                        attackPoint++;
                    }
                    movesForCurrentPosition.FlipPosition(new Position(this.GetCurrentPosition().GetColumn() + 1, attackPoint));
                }
            }
        }

        return(movesForCurrentPosition);
    }