示例#1
0
        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);
        }
示例#2
0
        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);
                }
            }
        }
示例#3
0
        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");
        }
示例#4
0
        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");
        }
示例#5
0
        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);
            }
        }
示例#6
0
        /// <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);
        }
示例#7
0
        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);
            }
        }
示例#8
0
        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
            });
        }
示例#9
0
        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");
        }
示例#10
0
        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);
        }
示例#11
0
        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);
        }