public static WorthInPawn CalcWorthInPawns(this BoardSetup board) { var res = new WorthInPawn(); for (int f = 0; f < 8; f++) { for (int r = 0; r < 8; r++) { var p = board[f, r]; if (p == null) { continue; } if (p.Color == Color.White) { res.White += p.PieceType.WorthInPawns(); } else { res.Black += p.PieceType.WorthInPawns(); } } } return(res); }
public static Move[] ValidateMove(this BoardSetup board, Move move) { if (move.Type == MoveType.CastleKingSide || move.Type == MoveType.CastleQueenSide) { return(MoveHelper.ValidateCastle(move, board)); } else { switch (move.Piece) { case PieceType.Pawn: return(new[] { MoveHelper.ValidatePawnMove(move, board) }); case PieceType.Knight: return(new[] { MoveHelper.ValidateKnightMove(move, board) }); case PieceType.Bishop: return(new[] { MoveHelper.ValidateBishopMove(move, board) }); case PieceType.Rook: return(new[] { MoveHelper.ValidateRookMove(move, board) }); case PieceType.Queen: return(new[] { MoveHelper.ValidateQueenMove(move, board) }); case PieceType.King: return(new[] { MoveHelper.ValidateKingMove(move, board) }); default: return(null); } } }
public static Move[] ValidateCastle(Move move, BoardSetup board) { // Не проверяются битые поля на пути короля и то что ладья та самая bool kingSide = move.Type == MoveType.CastleKingSide; Color color = board.IsWhiteMove ? Color.White : Color.Black; if (color == Color.White && (kingSide == true && board.CanWhiteCastleKingSide == false || kingSide == false && board.CanWhiteCastleQueenSide == false) || color == Color.Black && (kingSide == true && board.CanBlackCastleKingSide == false || kingSide == false && board.CanBlackCastleQueenSide == false)) { throw new InvalidOperationException("This castling is no longer possible"); } int df = kingSide ? 1 : -1; int rank = board.IsWhiteMove ? 0 : 7; for (int f = 0; f < 8; f++) { if (board[f, rank]?.PieceType == PieceType.King && board[f, rank]?.Color == color) { for (int i = 1; i < 6; i++) { int nf = f + i * df; if (nf < 0 || nf > 7) { break; } if (board[nf, rank]?.PieceType == PieceType.Rook && board[nf, rank]?.Color == color) { var km = new Move(); km.Piece = PieceType.King; km.Type = MoveType.Simple; km.OriginSquare = new Square((File)(f + 1), rank + 1); km.OriginFile = km.OriginSquare.File; km.OriginRank = km.OriginSquare.Rank; km.TargetSquare = kingSide ? new Square(File.G, rank + 1) : new Square(File.C, rank + 1); km.TargetFile = km.TargetSquare.File; var rm = new Move(); rm.Piece = PieceType.Rook; rm.Type = MoveType.Simple; rm.OriginSquare = new Square((File)(nf + 1), rank + 1); rm.OriginFile = rm.OriginSquare.File; rm.OriginRank = rm.OriginSquare.Rank; rm.TargetSquare = kingSide ? new Square(File.F, rank + 1) : new Square(File.D, rank + 1); rm.TargetFile = rm.TargetSquare.File; return(new[] { km, rm }); } else if (board[nf, rank] != null) { throw new InvalidOperationException("A figure interferes with castling"); } } break; } } throw new InvalidOperationException("No castling rook found"); }
public static Move ValidatePawnMove(Move move, BoardSetup board) { var file = move.TargetSquare.File; var rank = move.TargetSquare.Rank; Color color = board.IsWhiteMove ? Color.White : Color.Black; int direction = color == Color.White ? 1 : -1; int pawnLine = color == Color.White ? 2 : 7; var targetPiece = board[move.TargetSquare]; var ppc = move.PromotedPiece == null || (move.PromotedPiece != PieceType.King && move.PromotedPiece != PieceType.Pawn); var isCorrectPawnArea = color == Color.White && rank >= 2 && rank <= 8 || color == Color.Black && rank >= 1 && rank <= 7; var result = move.Clone(); if (move.Type == MoveType.Simple) { if (targetPiece == null && ppc && isCorrectPawnArea == false) { throw new InvalidOperationException(); } if (board[file, rank - direction]?.PieceType == PieceType.Pawn && board[file, rank - direction]?.Color == color) { result.OriginFile = file; result.OriginRank = rank - direction; result.OriginSquare = new Square(result.OriginFile.Value, result.OriginRank.Value); return(result); } else if (board[file, rank - direction] == null && board[file, rank - 2 * direction]?.PieceType == PieceType.Pawn && board[file, rank - 2 * direction]?.Color == color && rank - 2 * direction == pawnLine) { result.OriginFile = file; result.OriginRank = rank - 2 * direction; result.OriginSquare = new Square(result.OriginFile.Value, result.OriginRank.Value); return(result); } } else if (move.Type == MoveType.Capture) { if (ppc && targetPiece != null && color != targetPiece.Color && isCorrectPawnArea && move.OriginFile.HasValue == false) { throw new InvalidOperationException(); } if (board[move.OriginFile.Value, rank - direction]?.Color == color && board[move.OriginFile.Value, rank - direction]?.PieceType == PieceType.Pawn) { result.OriginRank = rank - direction; result.OriginSquare = new Square(result.OriginFile.Value, result.OriginRank.Value); return(result); } } else if (move.Type == MoveType.CaptureEnPassant) { throw new NotImplementedException(); } throw new InvalidOperationException("No piece can make this move"); }
public static Move ValidateKingMove(Move move, BoardSetup board) { var asKing = ValidatePieceMove(move, board, PieceType.King, PieceType.King); if (asKing == null) { throw new InvalidOperationException("No piece can make this move"); } else { return(asKing); } }
/// <summary> /// Start position for classic chess /// </summary> /// <returns></returns> public static BoardSetup CreateDefault() { var b = new BoardSetup(); b[File.A, 1] = Piece.WhiteRook; b[File.B, 1] = Piece.WhiteKnight; b[File.C, 1] = Piece.WhiteBishop; b[File.D, 1] = Piece.WhiteQueen; b[File.E, 1] = Piece.WhiteKing; b[File.F, 1] = Piece.WhiteBishop; b[File.G, 1] = Piece.WhiteKnight; b[File.H, 1] = Piece.WhiteRook; b[File.A, 8] = Piece.BlackRook; b[File.B, 8] = Piece.BlackKnight; b[File.C, 8] = Piece.BlackBishop; b[File.D, 8] = Piece.BlackQueen; b[File.E, 8] = Piece.BlackKing; b[File.F, 8] = Piece.BlackBishop; b[File.G, 8] = Piece.BlackKnight; b[File.H, 8] = Piece.BlackRook; b[File.A, 2] = Piece.WhitePawn; b[File.B, 2] = Piece.WhitePawn; b[File.C, 2] = Piece.WhitePawn; b[File.D, 2] = Piece.WhitePawn; b[File.E, 2] = Piece.WhitePawn; b[File.F, 2] = Piece.WhitePawn; b[File.G, 2] = Piece.WhitePawn; b[File.H, 2] = Piece.WhitePawn; b[File.A, 7] = Piece.BlackPawn; b[File.B, 7] = Piece.BlackPawn; b[File.C, 7] = Piece.BlackPawn; b[File.D, 7] = Piece.BlackPawn; b[File.E, 7] = Piece.BlackPawn; b[File.F, 7] = Piece.BlackPawn; b[File.G, 7] = Piece.BlackPawn; b[File.H, 7] = Piece.BlackPawn; b.CanBlackCastleKingSide = true; b.CanBlackCastleQueenSide = true; b.CanWhiteCastleKingSide = true; b.CanWhiteCastleQueenSide = true; b.EnPassantSquare = null; b.FullMoveCount = 1; b.HalfMoveClock = 1; b.IsWhiteMove = true; return(b); }
public static Move ValidateQueenMove(Move move, BoardSetup board) { var asRook = ValidatePieceMove(move, board, PieceType.Queen, PieceType.Rook); var asBishop = ValidatePieceMove(move, board, PieceType.Queen, PieceType.Bishop); if (asBishop == null && asRook == null) { throw new InvalidOperationException("No piece can make this move"); } else { return(asRook ?? asBishop); } }
public static Position GoToMove(this Game game, int halfmove = int.MaxValue) { if (game.BoardSetup == null && game.Tags.ContainsKey("FEN") == false) { game.BoardSetup = BoardSetup.CreateDefault(); } var board = game.BoardSetup.Clone(); int cnt = 0; var sbMoves = new StringBuilder(); foreach (var move in game.MoveText.GetMoves()) { cnt++; var vmoves = board.ValidateMove(move); if (vmoves != null) { foreach (var vmove in vmoves) { if (vmove.TargetSquare != null) { board[vmove.TargetSquare] = board[vmove.OriginSquare]; } if (vmove.TargetSquare != vmove.OriginSquare) { board[vmove.OriginSquare] = null; } } sbMoves.Append(vmoves.First().ToUciString()); sbMoves.Append(" "); } board.IsWhiteMove = !board.IsWhiteMove; if (cnt >= halfmove) { break; } } return(new Position { Board = board, UciMoves = sbMoves.ToString(), HalfMove = cnt }); }
public static Move ValidateKnightMove(Move move, BoardSetup board) { var rank = move.TargetSquare.Rank - 1; var ifile = (int)move.TargetSquare.File - 1; Color color = board.IsWhiteMove ? Color.White : Color.Black; var targetPieceNotKing = board[move.TargetSquare]?.PieceType != PieceType.King && board[move.TargetSquare]?.Color != color; Func <int, int, bool> pieceCondition = (f, r) => Math.Abs(Math.Abs(ifile - f) - Math.Abs(rank - r)) == 1 && Math.Max(Math.Abs(ifile - f), Math.Abs(rank - r)) == 2; Square original = null; for (int f = 0; f < 8; f++) { for (int r = 0; r < 8; r++) { if (board[f, r]?.PieceType == PieceType.Knight && board[f, r]?.Color == color && pieceCondition(f, r) && targetPieceNotKing && (move.OriginRank == null || move.OriginRank == (r + 1)) && (move.OriginFile == null || move.OriginFile == (File)(f + 1))) { if (original == null) { original = new Square((File)(f + 1), r + 1); } else { throw new InvalidOperationException("More than one piece can make a given move"); } } } } if (original != null) { var result = move.Clone(); result.OriginSquare = original; result.OriginFile = original.File; result.OriginRank = original.Rank; return(result); } throw new InvalidOperationException("No piece can make this move"); }
public BoardSetup Clone() { var b = new BoardSetup(); b.CanBlackCastleKingSide = this.CanBlackCastleKingSide; b.CanBlackCastleQueenSide = this.CanBlackCastleQueenSide; b.CanWhiteCastleKingSide = this.CanWhiteCastleKingSide; b.CanWhiteCastleQueenSide = this.CanWhiteCastleQueenSide; b.EnPassantSquare = this.EnPassantSquare; b.FullMoveCount = this.FullMoveCount; b.HalfMoveClock = this.HalfMoveClock; b.IsWhiteMove = this.IsWhiteMove; for (int i = 0; i < b._board.GetLength(0); i++) { for (int j = 0; j < b._board.GetLength(1); j++) { b._board[i, j] = this._board[i, j]; } } return(b); }
static Move ValidatePieceMove(Move move, BoardSetup board, PieceType piece, PieceType pieceType) { var rank = move.TargetSquare.Rank - 1; var ifile = (int)move.TargetSquare.File - 1; Color color = board.IsWhiteMove ? Color.White : Color.Black; var targetPieceNotKing = board[move.TargetSquare]?.PieceType != PieceType.King && board[move.TargetSquare]?.Color != color; Func <int, int, bool> pieceCondition; if (pieceType == PieceType.Bishop) { pieceCondition = (f, r) => Math.Abs(ifile - f) == Math.Abs(rank - r); } else if (pieceType == PieceType.Rook) { pieceCondition = (f, r) => (ifile == f || rank == r); } else if (pieceType == PieceType.King) { pieceCondition = (f, r) => Math.Abs(ifile - f) <= 1 && Math.Abs(rank - r) <= 1; } else { throw new InvalidOperationException("Invalid piece was passed to func"); } Square original = null; for (int f = 0; f < 8; f++) { for (int r = 0; r < 8; r++) { if (board[f, r]?.PieceType == piece && board[f, r]?.Color == color && pieceCondition(f, r) && targetPieceNotKing && (move.OriginRank == null || move.OriginRank == (r + 1)) && (move.OriginFile == null || move.OriginFile == (File)(f + 1))) { int pathLenght = Math.Abs(ifile - f); int df = Math.Sign(ifile - f); int dr = Math.Sign(rank - r); bool freePath = true; for (int i = 1; i < pathLenght; i++) { if (board[f + df * i, r + dr * i] != null) { freePath = false; break; } } if (freePath == true) { if (original == null) { original = new Square((File)(f + 1), r + 1); } else { throw new InvalidOperationException("More than one piece can make a given move"); } } } } } if (original != null) { var result = move.Clone(); result.OriginSquare = original; result.OriginFile = original.File; result.OriginRank = original.Rank; return(result); } return(null); }