// 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))); } }
public bool IsSameCells(Move other) { return FromCell == other.FromCell && ToCell == other.ToCell; }
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)); } }