/// <summary> /// Slide along the path steps until you hit something. Return path to point and if it ends attacking with the attack. /// </summary> private static List <position_t> Slide(ChessBoard board, Player p, position_t pos, position_t step) { List <position_t> moves = new List <position_t>(); for (int i = 1; i < 8; i++) { position_t moved = new position_t(pos.letter + i * step.letter, pos.number + i * step.number); if (moved.letter < 0 || moved.letter > 7 || moved.number < 0 || moved.number > 7) { break; } if (board.Grid[moved.number][moved.letter].piece != Piece.NONE) { if (board.Grid[moved.number][moved.letter].player != p) { moves.Add(moved); } break; } moves.Add(moved); } return(moves); }
/// <summary> /// Checks to see if the king for a player is in check. This function /// works by pretending the king is each of the different board pieces and seeing if it can attack /// any of the same type of price from its current position. /// </summary> /// <param name="b">Board state</param> /// <param name="king">the currnet player</param> /// <returns>Is in check</returns> public static bool isCheck(ChessBoard b, Player king) { if (b.Kings.Count == 0) { return(true); } position_t king_pos = b.Kings[king]; if (king_pos.number < 0 || king_pos.letter < 0) { return(true); } Piece[] pieces = { Piece.PAWN, Piece.ROOK, Piece.KNIGHT, Piece.BISHOP, Piece.QUEEN, Piece.KING }; ChessBoard tempBoard = new ChessBoard(b); for (int i = 0; i < 6; i++) { tempBoard.Grid[king_pos.number][king_pos.letter] = new piece_t(pieces[i], king); List <position_t> moves = getLegalMove(tempBoard, king_pos, false); foreach (var move in moves) { if (b.Grid[move.number][move.letter].piece == pieces[i] && b.Grid[move.number][move.letter].player != king) { return(true); } } } return(false); }
/// <summary> /// Get any legal move from the current position on the provided board. /// </summary> /// <param name="board">The state of the game.</param> /// <param name="pos">The piece/position to check for valid moves.</param> /// <param name="verify_check">Whether or not to recurse and check if the current move puts you in check.</param> /// <returns>A list of positions the piece can move to.</returns> public static List <position_t> getLegalMove(ChessBoard board, position_t pos, bool verify_check = true) { piece_t p = board.Grid[pos.number][pos.letter]; if (p.piece == Piece.NONE) { return(new List <position_t>()); } switch (p.piece) { case Piece.PAWN: return(LegalMoveSet.Pawn(board, pos, verify_check)); case Piece.ROOK: return(LegalMoveSet.Rook(board, pos, verify_check)); case Piece.KNIGHT: return(LegalMoveSet.Knight(board, pos, verify_check)); case Piece.BISHOP: return(LegalMoveSet.Bishop(board, pos, verify_check)); case Piece.QUEEN: return(LegalMoveSet.Queen(board, pos, verify_check)); case Piece.KING: return(LegalMoveSet.King(board, pos, verify_check)); default: return(new List <position_t>()); } }
private static List <position_t> Rook(ChessBoard board, position_t pos, bool verify_check = true) { List <position_t> moves = new List <position_t>(); piece_t p = board.Grid[pos.number][pos.letter]; if (p.piece == Piece.NONE) { return(moves); } // slide along vert/hor for possible moves moves.AddRange(Slide(board, p.player, pos, new position_t(1, 0))); moves.AddRange(Slide(board, p.player, pos, new position_t(-1, 0))); moves.AddRange(Slide(board, p.player, pos, new position_t(0, 1))); moves.AddRange(Slide(board, p.player, pos, new position_t(0, -1))); if (verify_check)// make sure each move doesn't put us in check { for (int i = moves.Count - 1; i >= 0; i--) { ChessBoard b2 = LegalMoveSet.move(board, new move_t(pos, moves[i])); if (isCheck(b2, p.player)) { moves.RemoveAt(i); } } } return(moves); }
private static List <position_t> Knight(ChessBoard board, position_t pos, bool verify_check = true) { List <position_t> moves = new List <position_t>(); piece_t p = board.Grid[pos.number][pos.letter]; if (p.piece == Piece.NONE) { return(moves); } // collect all relative moves possible List <position_t> relative = new List <position_t>(); relative.Add(new position_t(2, 1)); relative.Add(new position_t(2, -1)); relative.Add(new position_t(-2, 1)); relative.Add(new position_t(-2, -1)); relative.Add(new position_t(1, 2)); relative.Add(new position_t(-1, 2)); relative.Add(new position_t(1, -2)); relative.Add(new position_t(-1, -2)); // iterate moves foreach (position_t move in relative) { position_t moved = new position_t(move.letter + pos.letter, move.number + pos.number); // bounds check if (moved.letter < 0 || moved.letter > 7 || moved.number < 0 || moved.number > 7) { continue; } // if empty space or attacking if (board.Grid[moved.number][moved.letter].piece == Piece.NONE || board.Grid[moved.number][moved.letter].player != p.player) { moves.Add(moved); } } if (verify_check)// make sure each move doesn't put us in check { for (int i = moves.Count - 1; i >= 0; i--) { ChessBoard b2 = LegalMoveSet.move(board, new move_t(pos, moves[i])); if (isCheck(b2, p.player)) { moves.RemoveAt(i); } } } return(moves); }
private static bool allowCastle(ChessBoard board, Player player, position_t pos, bool isRight) { bool isValid = true; int rookPos; int kingDirection; if (isRight) { rookPos = 7; kingDirection = 1; } else { rookPos = 0; kingDirection = -1; } //Check for valid right castling // Is the peice at H,7 a rook owned by the player and has it moved if (board.Grid[pos.number][rookPos].piece == Piece.ROOK && board.Grid[pos.number][rookPos].player == player && board.Grid[pos.number][rookPos].lastPosition.Equals(new position_t(-1, -1))) { // Check that the adjacent two squares are empty for (int i = 0; i < 2; i++) { if (board.Grid[pos.number][pos.letter + (i + 1) * kingDirection].piece != Piece.NONE) { isValid = false; break; } } // Don't bother running secondary checks if the way isn't even clear if (isValid) { for (int i = 0; i < 2; i++) { // Move kings postion over i squares to check if king is passing over an attackable // square ChessBoard b2 = LegalMoveSet.move(board, new move_t(pos, new position_t(pos.letter + (i + 1) * kingDirection, pos.number))); // Attackable square is in between king and rook so // its not possible to castle to the right rook if (isCheck(b2, player)) { isValid = false; break; } } } } else { isValid = false; } return(isValid); }
public void SetPiece(Piece piece, Player player, int letter, int number) { // set grid values Grid[number][letter].piece = piece; Grid[number][letter].player = player; // add piece to list Pieces[player].Add(new position_t(letter, number)); // update king position if (piece == Piece.KING) { Kings[player] = new position_t(letter, number); } }
public void SetRandomPlacement() { //Add the pieces via using the SetPiece() method //Check for placement, then add: Random r = new Random(); int letter = r.Next(0, 8), number = 0; //Pawns for (int i = 0; i < 8; i++) { SetPiece(Piece.PAWN, Player.WHITE, i, 1); SetPiece(Piece.PAWN, Player.BLACK, i, 6); } //Kings AssignPiece(Piece.KING, out letter, out number); Kings[Player.WHITE] = new position_t(letter, number); Kings[Player.BLACK] = new position_t(letter, Mirror(number)); //Rooks AssignPiece(Piece.ROOK, out letter, out number); AssignPiece(Piece.ROOK, out letter, out number); //Bishops AssignPiece(Piece.BISHOP, out letter, out number); BishopPos = new position_t(letter, number); //Somehow.. get where the bishop was placed. AssignPiece(Piece.BISHOP, out letter, out number); //Queens AssignPiece(Piece.QUEEN, out letter, out number); //Knights AssignPiece(Piece.KNIGHT, out letter, out number); AssignPiece(Piece.KNIGHT, out letter, out number); }
private static List <position_t> Pawn(ChessBoard board, position_t pos, bool verify_check = true) { List <position_t> moves = new List <position_t>(); piece_t p = board.Grid[pos.number][pos.letter]; if (p.piece == Piece.NONE) { return(moves); } // gather relative moves List <position_t> relative = new List <position_t>(); relative.Add(new position_t(-1, 1 * ((p.player == Player.BLACK) ? -1 : 1))); relative.Add(new position_t(0, 1 * ((p.player == Player.BLACK) ? -1 : 1))); relative.Add(new position_t(0, 2 * ((p.player == Player.BLACK) ? -1 : 1))); relative.Add(new position_t(1, 1 * ((p.player == Player.BLACK) ? -1 : 1))); // iterate moves foreach (position_t move in relative) { position_t moved = new position_t(move.letter + pos.letter, move.number + pos.number); // bounds check if (moved.letter < 0 || moved.letter > 7 || moved.number < 0 || moved.number > 7) { continue; } // double forward move if (moved.letter == pos.letter && board.Grid[moved.number][moved.letter].piece == Piece.NONE && Math.Abs(moved.number - pos.number) == 2) { // check the first step int step = -((moved.number - pos.number) / (Math.Abs(moved.number - pos.number))); bool hasnt_moved = pos.number == ((p.player == Player.BLACK) ? 6 : 1); if (board.Grid[moved.number + step][moved.letter].piece == Piece.NONE && hasnt_moved) { moves.Add(moved); } } // if it's not blocked we can move forward else if (moved.letter == pos.letter && board.Grid[moved.number][moved.letter].piece == Piece.NONE) { moves.Add(moved); } // angled attack else if (moved.letter != pos.letter && board.Grid[moved.number][moved.letter].piece != Piece.NONE && board.Grid[moved.number][moved.letter].player != p.player) { moves.Add(moved); } // en passant else if (isEnPassant(board, new move_t(pos, moved))) { moves.Add(moved); } } if (verify_check)// make sure each move doesn't put us in check { for (int i = moves.Count - 1; i >= 0; i--) { ChessBoard b2 = LegalMoveSet.move(board, new move_t(pos, moves[i])); if (isCheck(b2, p.player)) { moves.RemoveAt(i); } } } return(moves); }
private static List <position_t> King(ChessBoard board, position_t pos, bool verify_check = true) { List <position_t> moves = new List <position_t>(); piece_t p = board.Grid[pos.number][pos.letter]; if (p.piece == Piece.NONE) { return(moves); } // collect all relative moves possible List <position_t> relative = new List <position_t>(); relative.Add(new position_t(-1, 1)); relative.Add(new position_t(0, 1)); relative.Add(new position_t(1, 1)); relative.Add(new position_t(-1, 0)); relative.Add(new position_t(1, 0)); relative.Add(new position_t(-1, -1)); relative.Add(new position_t(0, -1)); relative.Add(new position_t(1, -1)); // Iterate moves foreach (position_t move in relative) { position_t moved = new position_t(move.letter + pos.letter, move.number + pos.number); // bound check if (moved.letter < 0 || moved.letter > 7 || moved.number < 0 || moved.number > 7) { continue; } // if it's not blocked we can move if (board.Grid[moved.number][moved.letter].piece == Piece.NONE || board.Grid[moved.number][moved.letter].player != p.player) { if (verify_check) // make sure we don't put ourselves in check { ChessBoard b2 = LegalMoveSet.move(board, new move_t(pos, moved)); if (!isCheck(b2, p.player)) { moves.Add(moved); } } else { moves.Add(moved); } } } // Castling /* A king can only castle if: * king has not moved * rook has not moved * king is not in check * king does not end up in check * king does not pass through any other peieces * king does not pass through any squares under attack * king knows secret handshake */ if (verify_check) { if (!isCheck(board, p.player) && p.lastPosition.Equals(new position_t(-1, -1))) { bool castleRight = allowCastle(board, p.player, pos, true); bool castleLeft = allowCastle(board, p.player, pos, false); if (castleRight) { moves.Add(new position_t(6, pos.number)); } if (castleLeft) { moves.Add(new position_t(2, pos.number)); } } } return(moves); }
/// <summary> /// Slide along the path steps until you hit something. Return path to point and if it ends attacking with the attack. /// </summary> private static List<position_t> Slide(ChessBoard board, Player p, position_t pos, position_t step) { List<position_t> moves = new List<position_t>(); for (int i = 1; i < 8; i++) { position_t moved = new position_t(pos.letter + i * step.letter, pos.number + i * step.number); if (moved.letter < 0 || moved.letter > 7 || moved.number < 0 || moved.number > 7) break; if (board.Grid[moved.number][moved.letter].piece != Piece.NONE) { if (board.Grid[moved.number][moved.letter].player != p) moves.Add(moved); break; } moves.Add(moved); } return moves; }
public List<position_t> Select(position_t pos) { // has previously selected something if (this.Board.Grid[this.Selection.number][this.Selection.letter].piece != Piece.NONE && this.Turn == this.Board.Grid[this.Selection.number][this.Selection.letter].player && (this.m_nPlayers == 2 || this.Turn == Player.WHITE)) { // get previous selections moves and determine if we chose a legal one by clicking List<position_t> moves = LegalMoveSet.getLegalMove(this.Board, this.Selection); foreach (position_t move in moves) { if (move.Equals(pos)) { // we selected a legal move so update the board MakeMove(new move_t(this.Selection, pos)); // If piece that was just moved is a king and it moved anyhthing other than 1 square, it was // a castling move, so we need to move the rook if (this.Board.Grid[pos.number][pos.letter].piece == Piece.KING && Math.Abs(pos.letter - this.Selection.letter) == 2) { int row = (this.Turn == Player.WHITE) ? 0 : 7; // Left rook if (pos.letter < 4) { LegalMoveSet.move(this.Board, new move_t(new position_t(0, row), new position_t(3, row))); } // right rook else { LegalMoveSet.move(this.Board, new move_t(new position_t(7, row), new position_t(5, row))); } } // finish move switchPlayer(); if (detectCheckmate()) return new List<position_t>(); if (this.m_nPlayers == 1) // start ai { new Thread(AISelect).Start(); // thread turn } return new List<position_t>(); } } } // first click, let's show possible moves if (this.Board.Grid[pos.number][pos.letter].player == this.Turn && (this.m_nPlayers == 2 || this.Turn == Player.WHITE)) { List<position_t> moves = LegalMoveSet.getLegalMove(this.Board, pos); this.Selection = pos; return moves; } // reset this.Selection = new position_t(); return new List<position_t>(); }
private static List<position_t> Pawn(ChessBoard board, position_t pos, bool verify_check = true) { List<position_t> moves = new List<position_t>(); piece_t p = board.Grid[pos.number][pos.letter]; if (p.piece == Piece.NONE) return moves; // gather relative moves List<position_t> relative = new List<position_t>(); relative.Add(new position_t(-1, 1 * ((p.player == Player.BLACK) ? -1 : 1))); relative.Add(new position_t(0, 1 * ((p.player == Player.BLACK) ? -1 : 1))); relative.Add(new position_t(0, 2 * ((p.player == Player.BLACK) ? -1 : 1))); relative.Add(new position_t(1, 1 * ((p.player == Player.BLACK) ? -1 : 1))); // iterate moves foreach (position_t move in relative) { position_t moved = new position_t(move.letter + pos.letter, move.number + pos.number); // bounds check if (moved.letter < 0 || moved.letter > 7 || moved.number < 0 || moved.number > 7) continue; // double forward move if (moved.letter == pos.letter && board.Grid[moved.number][moved.letter].piece == Piece.NONE && Math.Abs(moved.number - pos.number) == 2) { // check the first step int step = -((moved.number - pos.number) / (Math.Abs(moved.number - pos.number))); bool hasnt_moved = pos.number == ((p.player == Player.BLACK) ? 6 : 1); if (board.Grid[moved.number + step][moved.letter].piece == Piece.NONE && hasnt_moved) { moves.Add(moved); } } // if it's not blocked we can move forward else if (moved.letter == pos.letter && board.Grid[moved.number][moved.letter].piece == Piece.NONE) { moves.Add(moved); } // angled attack else if (moved.letter != pos.letter && board.Grid[moved.number][moved.letter].piece != Piece.NONE && board.Grid[moved.number][moved.letter].player != p.player) { moves.Add(moved); } // en passant else if(isEnPassant(board, new move_t(pos,moved))) { moves.Add(moved); } } if (verify_check)// make sure each move doesn't put us in check { for (int i = moves.Count - 1; i >= 0; i--) { ChessBoard b2 = LegalMoveSet.move(board, new move_t(pos, moves[i])); if (isCheck(b2, p.player)) { moves.RemoveAt(i); } } } return moves; }
private static List<position_t> Rook(ChessBoard board, position_t pos, bool verify_check = true) { List<position_t> moves = new List<position_t>(); piece_t p = board.Grid[pos.number][pos.letter]; if (p.piece == Piece.NONE) return moves; // slide along vert/hor for possible moves moves.AddRange(Slide(board, p.player, pos, new position_t(1, 0))); moves.AddRange(Slide(board, p.player, pos, new position_t(-1, 0))); moves.AddRange(Slide(board, p.player, pos, new position_t(0, 1))); moves.AddRange(Slide(board, p.player, pos, new position_t(0, -1))); if (verify_check)// make sure each move doesn't put us in check { for (int i = moves.Count - 1; i >= 0; i--) { ChessBoard b2 = LegalMoveSet.move(board, new move_t(pos, moves[i])); if (isCheck(b2, p.player)) { moves.RemoveAt(i); } } } return moves; }
private static List<position_t> Knight(ChessBoard board, position_t pos, bool verify_check = true) { List<position_t> moves = new List<position_t>(); piece_t p = board.Grid[pos.number][pos.letter]; if (p.piece == Piece.NONE) return moves; // collect all relative moves possible List<position_t> relative = new List<position_t>(); relative.Add(new position_t(2, 1)); relative.Add(new position_t(2, -1)); relative.Add(new position_t(-2, 1)); relative.Add(new position_t(-2, -1)); relative.Add(new position_t(1, 2)); relative.Add(new position_t(-1, 2)); relative.Add(new position_t(1, -2)); relative.Add(new position_t(-1, -2)); // iterate moves foreach (position_t move in relative) { position_t moved = new position_t(move.letter + pos.letter, move.number + pos.number); // bounds check if (moved.letter < 0 || moved.letter > 7 || moved.number < 0 || moved.number > 7) continue; // if empty space or attacking if (board.Grid[moved.number][moved.letter].piece == Piece.NONE || board.Grid[moved.number][moved.letter].player != p.player) moves.Add(moved); } if (verify_check)// make sure each move doesn't put us in check { for (int i = moves.Count - 1; i >= 0; i--) { ChessBoard b2 = LegalMoveSet.move(board, new move_t(pos, moves[i])); if (isCheck(b2, p.player)) { moves.RemoveAt(i); } } } return moves; }
private static bool allowCastle(ChessBoard board, Player player, position_t pos, bool isRight) { bool isValid = true; int rookPos; int kingDirection; if (isRight) { rookPos = 7; kingDirection = 1; } else { rookPos = 0; kingDirection = -1; } //Check for valid right castling // Is the peice at H,7 a rook owned by the player and has it moved if (board.Grid[pos.number][rookPos].piece == Piece.ROOK && board.Grid[pos.number][rookPos].player == player && board.Grid[pos.number][rookPos].lastPosition.Equals(new position_t(-1,-1))) { // Check that the adjacent two squares are empty for (int i = 0; i < 2; i++) { if (board.Grid[pos.number][pos.letter + (i + 1) * kingDirection].piece != Piece.NONE) { isValid = false; break; } } // Don't bother running secondary checks if the way isn't even clear if (isValid) { for (int i = 0; i < 2; i++) { // Move kings postion over i squares to check if king is passing over an attackable // square ChessBoard b2 = LegalMoveSet.move(board, new move_t(pos, new position_t(pos.letter + (i + 1) * kingDirection, pos.number))); // Attackable square is in between king and rook so // its not possible to castle to the right rook if (isCheck(b2, player)) { isValid = false; break; } } } } else { isValid = false; } return isValid; }
private static List<position_t> King(ChessBoard board, position_t pos, bool verify_check = true) { List<position_t> moves = new List<position_t>(); piece_t p = board.Grid[pos.number][pos.letter]; if (p.piece == Piece.NONE) return moves; // collect all relative moves possible List<position_t> relative = new List<position_t>(); relative.Add(new position_t(-1, 1)); relative.Add(new position_t(0, 1)); relative.Add(new position_t(1, 1)); relative.Add(new position_t(-1, 0)); relative.Add(new position_t(1, 0)); relative.Add(new position_t(-1, -1)); relative.Add(new position_t(0, -1)); relative.Add(new position_t(1, -1)); // Iterate moves foreach (position_t move in relative) { position_t moved = new position_t(move.letter + pos.letter, move.number + pos.number); // bound check if (moved.letter < 0 || moved.letter > 7 || moved.number < 0 || moved.number > 7) continue; // if it's not blocked we can move if (board.Grid[moved.number][moved.letter].piece == Piece.NONE || board.Grid[moved.number][moved.letter].player != p.player) { if (verify_check) // make sure we don't put ourselves in check { ChessBoard b2 = LegalMoveSet.move(board, new move_t(pos, moved)); if(!isCheck(b2, p.player)) { moves.Add(moved); } } else { moves.Add(moved); } } } // Castling /* A king can only castle if: * king has not moved * rook has not moved * king is not in check * king does not end up in check * king does not pass through any other peieces * king does not pass through any squares under attack * king knows secret handshake */ if (verify_check) { if (!isCheck(board, p.player) && p.lastPosition.Equals(new position_t(-1,-1))) { bool castleRight = allowCastle(board, p.player, pos, true); bool castleLeft = allowCastle(board, p.player, pos, false); if (castleRight) { moves.Add(new position_t(6, pos.number)); } if (castleLeft) { moves.Add(new position_t(2, pos.number)); } } } return moves; }
public List <position_t> Select(position_t pos) { // has previously selected something if (this.Board.Grid[this.Selection.number][this.Selection.letter].piece != Piece.NONE && this.Turn == this.Board.Grid[this.Selection.number][this.Selection.letter].player && (this.m_nPlayers == 2 || this.Turn == Player.WHITE)) { // get previous selections moves and determine if we chose a legal one by clicking List <position_t> moves = LegalMoveSet.getLegalMove(this.Board, this.Selection); foreach (position_t move in moves) { if (move.Equals(pos)) { // we selected a legal move so update the board MakeMove(new move_t(this.Selection, pos)); // If piece that was just moved is a king and it moved anyhthing other than 1 square, it was // a castling move, so we need to move the rook if (this.Board.Grid[pos.number][pos.letter].piece == Piece.KING && Math.Abs(pos.letter - this.Selection.letter) == 2) { int row = (this.Turn == Player.WHITE) ? 0 : 7; // Left rook if (pos.letter < 4) { LegalMoveSet.move(this.Board, new move_t(new position_t(0, row), new position_t(3, row))); } // right rook else { LegalMoveSet.move(this.Board, new move_t(new position_t(7, row), new position_t(5, row))); } } // finish move switchPlayer(); if (detectCheckmate()) { return(new List <position_t>()); } if (this.m_nPlayers == 1) // start ai { new Thread(AISelect).Start(); // thread turn } return(new List <position_t>()); } } } // first click, let's show possible moves if (this.Board.Grid[pos.number][pos.letter].player == this.Turn && (this.m_nPlayers == 2 || this.Turn == Player.WHITE)) { List <position_t> moves = LegalMoveSet.getLegalMove(this.Board, pos); this.Selection = pos; return(moves); } // reset this.Selection = new position_t(); return(new List <position_t>()); }
/// <summary> /// Get any legal move from the current position on the provided board. /// </summary> /// <param name="board">The state of the game.</param> /// <param name="pos">The piece/position to check for valid moves.</param> /// <param name="verify_check">Whether or not to recurse and check if the current move puts you in check.</param> /// <returns>A list of positions the piece can move to.</returns> public static List<position_t> getLegalMove(ChessBoard board, position_t pos, bool verify_check = true) { piece_t p = board.Grid[pos.number][pos.letter]; if (p.piece == Piece.NONE) return new List<position_t>(); switch (p.piece) { case Piece.PAWN: return LegalMoveSet.Pawn(board, pos, verify_check); case Piece.ROOK: return LegalMoveSet.Rook(board, pos, verify_check); case Piece.KNIGHT: return LegalMoveSet.Knight(board, pos, verify_check); case Piece.BISHOP: return LegalMoveSet.Bishop(board, pos, verify_check); case Piece.QUEEN: return LegalMoveSet.Queen(board, pos, verify_check); case Piece.KING: return LegalMoveSet.King(board, pos, verify_check); default: return new List<position_t>(); } }