// TODO - consider removing
 //public Fingerprint Fingerprint { get; set; }
 public AnalysisNode(AnalysisNode parent, Position.Position p, Move m)
 {
     Debug.Assert(p != null);
     Parent = parent;
     // Must init ParentMove before Position
     m_parent_move = m;
     Position = p;
     Children = null;
     IsWhiteToMove = p.IsWhiteToMove;
 }
 public static bool IsMyMovePutsMyKingInCheck(Players player_who_moved, Move m,
     Position.Position p, bool is_king_was_in_check_before_the_move)
 {
     Debug.Assert(!m.IsNullMove);
     if (is_king_was_in_check_before_the_move || m.Piece == Pieces.King)
     {
         // Cannot optimize - do a full check
         var king_cell = new ChessboardCell(p.GetPieces(player_who_moved).KingsCell);
         return PositionHelper.IsCellAttacked(king_cell, p.PlayerToMove, p);
     }
     else
     {
         // My king can only be attacked now along the line between the king
         // and the cell, from where my piece has moved
         var player_to_move = p.PlayerToMove;
         var king_cell = new ChessboardCell(
             p.GetPieces(Helper.GetOtherPlayer(player_to_move)).KingsCell);
         return PositionHelper.IsCellAttackedFromDir(king_cell,
             new ChessboardCell(m.FromCell),
             p.GetPieces(p.PlayerToMove),
             p.GetPieces(Helper.GetOtherPlayer(p.PlayerToMove)));
     }
 }
Exemple #3
0
 public bool IsSameCells(Move other)
 {
     return FromCell == other.FromCell && ToCell == other.ToCell;
 }
Exemple #4
0
        public Position PlayMove(Move move)
        {
            // 'My' refers to player to move, 'other' refers to other player
            var my_player = PlayerToMove;
            var other_player = Helper.GetOtherPlayer(my_player);

            var my_pieces = GetPieces(my_player);
            var other_pieces = GetPieces(other_player);

            PlayerPieceSet new_my_pieces = null;
            if (move.IsPromotion)
            {
                Debug.Assert(move.Piece == Exports.Pieces.Pawn);
                var tmp_pieces = PlayerPieceSet.RemovePiece(my_pieces,
                    Exports.Pieces.Pawn, move.FromCell);
                new_my_pieces = PlayerPieceSet.InsertPiece(tmp_pieces,
                    move.PromoteToPiece, move.ToCell);
            }
            else if (move.IsShortCastle || move.IsLongCastle)
            {
                int base_row = my_player == Players.White ?
                    Chessboard.ROW_MIN : Chessboard.ROW_MAX;
                Debug.Assert(move.Piece == Exports.Pieces.King);
                var tmp_pieces = PlayerPieceSet.MovePiece(my_pieces,
                    Exports.Pieces.King, move.FromCell, move.ToCell);

                if (move.IsShortCastle)
                {
                    new_my_pieces = PlayerPieceSet.MovePiece(tmp_pieces,
                        Exports.Pieces.Rook,
                        ChessboardCell.CalculateValue(base_row, Chessboard.COLUMN_H),
                        ChessboardCell.CalculateValue(base_row, Chessboard.COLUMN_F));
                }
                else
                {
                    new_my_pieces = PlayerPieceSet.MovePiece(tmp_pieces,
                        Exports.Pieces.Rook,
                        ChessboardCell.CalculateValue(base_row, Chessboard.COLUMN_A),
                        ChessboardCell.CalculateValue(base_row, Chessboard.COLUMN_D));
                }
            }
            else
            {
                new_my_pieces = PlayerPieceSet.MovePiece(my_pieces,
                    move.Piece, move.FromCell, move.ToCell);
            }

            PlayerPieceSet new_other_pieces = null;
            if (move.IsCapture)
            {
                Exports.Pieces piece_to_remove = Exports.Pieces.NoPiece;
                int remove_piece_at = 0;
                if (move.IsEnPassantCapture)
                {
                    var move_to_cell = new ChessboardCell(move.ToCell);
                    remove_piece_at = ChessboardCell.CalculateValue(
                        move_to_cell.Row + (IsWhiteToMove ? -1 : 1),
                        move_to_cell.Column);
                    // Only pawns can capture en passant
                    piece_to_remove = Exports.Pieces.Pawn;
                }
                else
                {
                    remove_piece_at = move.ToCell;
                    piece_to_remove = other_pieces.GetPieceAtCell(remove_piece_at);
                }
                new_other_pieces = PlayerPieceSet.RemovePiece(other_pieces,
                    piece_to_remove, remove_piece_at);
            }
            else
            {
                // No change to other player's pieces, re-use the object
                new_other_pieces = other_pieces;
            }

            // TODO - consider memory pooling here
            var result = new Position();
            var new_white_pieces =
                IsWhiteToMove ? new_my_pieces : new_other_pieces;
            var new_black_pieces =
                IsWhiteToMove ? new_other_pieces : new_my_pieces;

            int? new_en_passant_capture_column = null;
            if (move.Piece == Exports.Pieces.Pawn)
            {
                var from = new ChessboardCell(move.FromCell);
                var to_row = new ChessboardCell(move.ToCell).Row;
                if (Math.Abs(from.Row - to_row) == 2)
                {
                    new_en_passant_capture_column = from.Column;
                }
            }

            var new_fullmove_number = FullmoveNumber;
            if (other_player == Players.White)
            {
                ++new_fullmove_number;
            }

            var new_halfmove_clock = HalfmoveClock + 1;
            if (move.Piece == Exports.Pieces.Pawn || move.IsCapture)
            {
                new_halfmove_clock = 0;
            }

            var new_white_castling_options = CalcNewCastlingOptions(Players.White,
                new_white_pieces, Chessboard.ROW_MIN);
            var new_black_castling_options = CalcNewCastlingOptions(Players.Black,
                new_black_pieces, Chessboard.ROW_MAX);

            result.Reset(new_white_pieces,
                new_black_pieces,
                other_player,
                new_white_castling_options,
                new_black_castling_options,
                new_en_passant_capture_column,
                new_fullmove_number,
                (ushort)new_halfmove_clock);

            return result;
        }
        public static bool IsMyMoveAttacksTheKing(Move m, Position position_after_move)
        {
            Debug.Assert(!m.IsSameCells(Move.NULL_MOVE));
            var moved_to_cell = new ChessboardCell(m.ToCell);
            var kings_cell = new ChessboardCell(position_after_move.GetPieces(
                position_after_move.PlayerToMove).KingsCell);
            var attacking_player = Helper.GetOtherPlayer(
                position_after_move.PlayerToMove);
            var attacking_pieces = position_after_move.GetPieces(attacking_player);
            var defending_pieces = position_after_move.GetPieces(
                Helper.GetOtherPlayer(attacking_player));

            // TODO
            // Check if the piece which moved attacks the king
            // Promotions shall be respected there
            switch (m.IsPromotion ? m.PromoteToPiece : m.Piece)
            {
                case Exports.Pieces.Pawn:
                    int pawn_move_row_delta = attacking_player == Players.White ? 1 : -1;
                    if (IsPawnAttacks(moved_to_cell, kings_cell, pawn_move_row_delta))
                    {
                        return true;
                    }
                    break;

                case Exports.Pieces.Knight:
                    if (IsKnightAttacks(moved_to_cell, kings_cell))
                    {
                        return true;
                    }
                    break;

                case Exports.Pieces.Bishop:
                    if (IsBishopAttacks(moved_to_cell, kings_cell,
                        attacking_pieces, defending_pieces))
                    {
                        return true;
                    }
                    break;

                case Exports.Pieces.Rook:
                    if (IsRookAttacks(moved_to_cell, kings_cell,
                        attacking_pieces, defending_pieces))
                    {
                        return true;
                    }
                    break;

                case Exports.Pieces.Queen:
                    if (IsQueenAttacks(moved_to_cell, kings_cell,
                        attacking_pieces, defending_pieces))
                    {
                        return true;
                    }
                    break;

                case Exports.Pieces.King:
                    {
                        // Castling can put opponent's king in check
                        if (m.IsShortCastle || m.IsLongCastle)
                        {
                            var rook_cell = new ChessboardCell(
                                moved_to_cell.Row,
                                m.IsShortCastle ? Chessboard.COLUMN_F
                                : Chessboard.COLUMN_C);
                            if (IsRookAttacks(rook_cell, kings_cell, attacking_pieces,
                                defending_pieces))
                            {
                                return true;
                            }
                        }
                    }
                    break;
            }

            // Check if the piece behind the piece which moved attacks the king
            return IsCellAttackedFromDir(kings_cell, new ChessboardCell(m.FromCell),
                attacking_pieces, defending_pieces);
        }
 public void SetRoot(Position.Position p, Move parent_move)
 {
     Clean();
     if (p != null)
     {
         Root = new AnalysisNode(null, p, parent_move);
         m_node_count = 1;
         // Probably this position was not analyzed yet, and IsInCheck
         // is not initialized yet. Evaluate and set IsInCheck flag
         p.IsInCheck = PositionHelper.IsCellAttacked(
             new ChessboardCell(p.GetPieces(p.PlayerToMove).KingsCell),
             Helper.GetOtherPlayer(p.PlayerToMove), p);
         // For root we want to create children and grandchildren
         // To detect stalemate or checkmate
         GenerateAllChildren(Root, 2);
     }
     m_listener.RootPositionChanged(p);
 }
 private static void WritePawnMove(int from_cell, int to_cell, uint cell_index,
     Move.Flags flags, List<Move> moves)
 {
     var to_cell_obj = new ChessboardCell(to_cell);
     if (to_cell_obj.Row == Chessboard.ROW_MIN
         || to_cell_obj.Row == Chessboard.ROW_MAX)
     {
         foreach (var promotion in m_pawn_promotions)
         {
             moves.Add(new Move(from_cell, to_cell,
                 flags | Move.Flags.Promotion, promotion));
         }
     }
     else
     {
         moves.Add(new Move(Exports.Pieces.Pawn, from_cell, to_cell,
             cell_index, flags));
     }
 }