public List <Piece> GetPiecesOfColour(Piece.PieceColour colour) { List <Piece> pieces = new List <Piece>(); foreach (Piece piece in this.pieces) { if (piece.colour == colour) { pieces.Add(piece); } } return(pieces); }
public static List <Move> GeneratePseudoLegalMoves(Board board, Piece.PieceColour colour_to_move) { var moves = new List <Move>(); for (int start_x = 0; start_x < Board.GridSize; start_x++) { for (int start_y = 0; start_y < Board.GridSize; start_y++) { Piece piece = board.Cells[start_x, start_y]; var start_cell = new Vector2Int(start_x, start_y); var this_piece_moves = new List <Move>(); if (piece.MyPieceColour == colour_to_move) { if (piece.IsSlidingPiece) { this_piece_moves = _GenerateSlidingMoves(start_cell, board.Cells); } else if (piece.MyPieceType == Piece.PieceType.Pawn) { this_piece_moves = _GeneratePawnMoves(start_cell, board.Cells); } else if (piece.MyPieceType == Piece.PieceType.Knight) { this_piece_moves = _GenerateKnightMoves(start_cell, board.Cells); } else if (piece.MyPieceType == Piece.PieceType.King) { this_piece_moves = _GenerateKingMoves(start_cell, board.Cells); } } foreach (Move move in this_piece_moves) { moves.Add(move); } } } return(moves); }
public static List <Move> GenerateMoves(Board board, Piece.PieceColour colour) { List <Move> moves = GeneratePseudoLegalMoves(board, colour); Piece.PieceColour opponent_colour = colour == Piece.PieceColour.White ? Piece.PieceColour.Black : Piece.PieceColour.White; List <Move> pruned_moves = new(); #region verify normal moves foreach (Move move in moves) { Board test_board = Board.SimulateMove(move, board); Vector2Int king_square = default; for (var y = 0; y < Board.GridSize; y++) { for (var x = 0; x < Board.GridSize; x++) { if (test_board.Cells[x, y].MyPieceType == Piece.PieceType.King && test_board.Cells[x, y].MyPieceColour == board.ColourToMove) { king_square = new Vector2Int(x, y); } } } //order is important - make move, simulate based on board after that move so pins work //we can use pseudolegal moves because even if the piece is pinned, it still counts as being able to capture the king List <Move> opponent_responses = GeneratePseudoLegalMoves(test_board, opponent_colour); if (opponent_responses.Any(response => response.TargetSquare == king_square)) { //opponent can capture king - so last move was illegal } else { pruned_moves.Add(move); } } #endregion #region castling Vector2Int king_start_square = default; for (var y = 0; y < Board.GridSize; y++) { for (var x = 0; x < Board.GridSize; x++) { if (board.Cells[x, y].MyPieceType == Piece.PieceType.King && board.Cells[x, y].MyPieceColour == board.ColourToMove) { king_start_square = new Vector2Int(x, y); } } } for (int y = 0; y < Board.GridSize; y++) { for (int x = 0; x < Board.GridSize; x++) { Piece piece = board.Cells[x, y]; Piece king = board.Cells[king_start_square.x, king_start_square.y]; List <Move> opponent_moves = GeneratePseudoLegalMoves(board, opponent_colour); bool fen_castle_kingside = board.ColourToMove == Piece.PieceColour.White ? board.fen_white_kingside_castle : board.fen_black_kingside_castle; bool fen_castle_queenside = board.ColourToMove == Piece.PieceColour.White ? board.fen_white_queenside_castle : board.fen_black_queenside_castle; #region kingside if (piece.MyPieceType == Piece.PieceType.Rook && x > king_start_square.x && piece.MyPieceColour == board.ColourToMove && king_start_square.y == y && Math.Abs(king_start_square.x - x) == 3 && !piece.HasMovedBefore && !king.HasMovedBefore && fen_castle_kingside) { var rook_start_square = new Vector2Int(x, y); bool passing_through_check = false; bool piece_in_way = false; //check if KING is passing through check or starting in check for (var i = 0; i < 3; i++) { if (opponent_moves.Any(response => response.TargetSquare == new Vector2Int(king_start_square.x + i, king_start_square.y))) { passing_through_check = true; } } //check if there are any pieces in the way for (var i = 1; i < 3; i++) { if (board.Cells[king_start_square.x + i, king_start_square.y].MyPieceType != Piece.PieceType.None) { piece_in_way = true; } } //are we allowed to castle? if (!passing_through_check && !piece_in_way) { var king_target_square = new Vector2Int(king_start_square.x + 2, king_start_square.y); pruned_moves.Add(new Move(king_start_square, king_target_square, true)); } } #endregion #region queenside else if (piece.MyPieceType == Piece.PieceType.Rook && x < king_start_square.x && piece.MyPieceColour == board.ColourToMove && king_start_square.y == y && Math.Abs(king_start_square.x - x) == 4 && !piece.HasMovedBefore && !king.HasMovedBefore && fen_castle_queenside) { var rook_start_square = new Vector2Int(x, y); bool passing_through_check = false; bool piece_in_way = false; for (var i = 0; i > -3; i--) { if (opponent_moves.Any(response => response.TargetSquare == new Vector2Int(king_start_square.x + i, king_start_square.y))) { passing_through_check = true; } } for (var i = 1; i < 4; i++) { if (board.Cells[rook_start_square.x + i, rook_start_square.y].MyPieceType != Piece.PieceType.None) { piece_in_way = true; } } if (!piece.HasMovedBefore && !king.HasMovedBefore && !passing_through_check && !piece_in_way) { var king_target_square = new Vector2Int(king_start_square.x - 2, king_start_square.y); pruned_moves.Add(new Move(king_start_square, king_target_square, true)); } } #endregion } } #endregion return(pruned_moves); }
public static List <Move> GenerateMoves(Board board) { Piece.PieceColour colour = board.ColourToMove; return(GenerateMoves(board, colour)); }
private bool isSquareAttackedByOtherSide(Vector2 pos, Piece.PieceColour colour) { if (colour == Piece.PieceColour.Black) { colour = Piece.PieceColour.White; } else { colour = Piece.PieceColour.Black; } List <Vector2> attacks = new List <Vector2>(); foreach (Piece piece in board.GetPiecesOfColour(colour)) { switch (piece.type) { case Piece.PieceType.Pawn: if (piece.colour == Piece.PieceColour.White) { attacks.Add(new Vector2(piece.BoardPosition.x + 1, piece.BoardPosition.y + 1)); attacks.Add(new Vector2(piece.BoardPosition.x - 1, piece.BoardPosition.y + 1)); } if (piece.colour == Piece.PieceColour.Black) { attacks.Add(new Vector2(piece.BoardPosition.x + 1, piece.BoardPosition.y - 1)); attacks.Add(new Vector2(piece.BoardPosition.x - 1, piece.BoardPosition.y - 1)); } break; case Piece.PieceType.Knight: for (int i = -1; i < 2; i += 2) { for (int j = -1; j < 2; j += 2) { Vector2 checkpos = new Vector2(piece.BoardPosition.x + 2 * i, piece.BoardPosition.y + 1 * j); attacks.Add(checkpos); } } for (int i = -1; i < 2; i += 2) { for (int j = -1; j < 2; j += 2) { Vector2 checkpos = new Vector2(piece.BoardPosition.x + 1 * i, piece.BoardPosition.y + 2 * j); if (!board.isSquareOccupied(checkpos)) { attacks.Add(checkpos); } else { if (board.GetPieceOnSquare(checkpos).colour != piece.colour) { attacks.Add(checkpos); } } } } break; case Piece.PieceType.Bishop: for (int i = -1; i < 2; i += 2) { for (int j = -1; j < 2; j += 2) { bool inbounds = true; bool foundPiece = false; Vector2 checkpos = new Vector2(piece.BoardPosition.x + i, piece.BoardPosition.y + j); inbounds = isPosInBounds(checkpos); while (inbounds && !foundPiece) { if (board.isSquareOccupied(checkpos)) { foundPiece = true; } attacks.Add(checkpos); checkpos = new Vector2(checkpos.x + i, checkpos.y + j); inbounds = isPosInBounds(checkpos); } } } break; case Piece.PieceType.Rook: for (int i = -1; i < 2; i += 2) { Vector2 checkpos = new Vector2(piece.BoardPosition.x + i, piece.BoardPosition.y); bool inbounds = true; bool foundPiece = false; inbounds = isPosInBounds(checkpos); while (inbounds && !foundPiece) { if (board.isSquareOccupied(checkpos)) { foundPiece = true; } attacks.Add(checkpos); checkpos = new Vector2(checkpos.x + i, checkpos.y); inbounds = isPosInBounds(checkpos); } } for (int i = -1; i < 2; i += 2) { Vector2 checkpos = new Vector2(piece.BoardPosition.x, piece.BoardPosition.y + i); bool inbounds = true; bool foundPiece = false; inbounds = isPosInBounds(checkpos); while (inbounds && !foundPiece) { if (board.isSquareOccupied(checkpos)) { foundPiece = true; } attacks.Add(checkpos); checkpos = new Vector2(checkpos.x, checkpos.y + i); inbounds = isPosInBounds(checkpos); } } break; case Piece.PieceType.Queen: for (int i = -1; i < 2; i += 2) { for (int j = -1; j < 2; j += 2) { bool inbounds = true; bool foundPiece = false; Vector2 checkpos = new Vector2(piece.BoardPosition.x + i, piece.BoardPosition.y + j); inbounds = isPosInBounds(checkpos); while (inbounds && !foundPiece) { if (board.isSquareOccupied(checkpos)) { foundPiece = true; } attacks.Add(checkpos); checkpos = new Vector2(checkpos.x + i, checkpos.y + j); inbounds = isPosInBounds(checkpos); } } } for (int i = -1; i < 2; i += 2) { Vector2 checkpos = new Vector2(piece.BoardPosition.x + i, piece.BoardPosition.y); bool inbounds = true; bool foundPiece = false; inbounds = isPosInBounds(checkpos); while (inbounds && !foundPiece) { if (board.isSquareOccupied(checkpos)) { foundPiece = true; } attacks.Add(checkpos); checkpos = new Vector2(checkpos.x + i, checkpos.y); inbounds = isPosInBounds(checkpos); } } for (int i = -1; i < 2; i += 2) { Vector2 checkpos = new Vector2(piece.BoardPosition.x, piece.BoardPosition.y + i); bool inbounds = true; bool foundPiece = false; inbounds = isPosInBounds(checkpos); while (inbounds && !foundPiece) { if (board.isSquareOccupied(checkpos)) { foundPiece = true; } attacks.Add(checkpos); checkpos = new Vector2(checkpos.x, checkpos.y + i); inbounds = isPosInBounds(checkpos); } } break; case Piece.PieceType.King: for (int i = -1; i < 2; i += 2) { for (int j = -1; j < 2; j += 2) { bool inbounds = true; Vector2 checkpos = new Vector2(piece.BoardPosition.x + i, piece.BoardPosition.y + j); inbounds = isPosInBounds(checkpos); if (inbounds) { attacks.Add(checkpos); } } } for (int i = -1; i < 2; i += 2) { Vector2 checkpos = new Vector2(piece.BoardPosition.x + i, piece.BoardPosition.y); bool inbounds = true; inbounds = isPosInBounds(checkpos); if (inbounds) { attacks.Add(checkpos); } } for (int i = -1; i < 2; i += 2) { Vector2 checkpos = new Vector2(piece.BoardPosition.x, piece.BoardPosition.y + i); bool inbounds = true; inbounds = isPosInBounds(checkpos); if (inbounds) { attacks.Add(checkpos); } } break; } } return(attacks.Contains(pos)); }