예제 #1
0
        static void Main(string[] args)
        {
            // Let's start by creating a chess game instance.
            ChessGame game = new ChessGame();

            // Now the game's board is in the start position and it's white's turn.
            Console.WriteLine("It's this color's turn: {0}", game.WhoseTurn);

            // This is how to find out which piece is at a certain position:
            Piece pieceAtA1 = game.GetPieceAt(new Position("A1")); // Or "a1", the casing doesn't matter
            /* There are other overloading options as well:
             * game.GetPieceAt(new Position(File.A, 1));
             * game.GetPieceAt(File.A, 1);
             * All those three options return the same. */
            Console.WriteLine("What piece is there at A1? {0}", pieceAtA1.GetFenCharacter());
            // GetFenCharacter() returns the FEN character for the given piece. White piece: uppercase, black piece: lowercase. The character is the first char of a piece's name (exception: Knight -> N/n because King -> K/k).
            // The Piece class is the abstract base class for pieces. All piece classes (e.g. Rook) derive from this class.

            // White has to make a turn. They want to move their E2 pawn to E4. Is that valid?
            Move e2e4 = new Move("E2", "E4", Player.White);
            bool isValid = game.IsValidMove(e2e4);
            Console.WriteLine("E2-E4 for white is valid: {0}", isValid);

            // Great, it's valid! So white wants to actually make that move.
            MoveType type = game.ApplyMove(e2e4, true);
            // The first argument is the move, the second argument indicates whether it's already validated. Here it is, so pass 'true'. If it's not validated yet, ApplyMove will do it. **Only pass `true` if it's really validated! If you pass `true`, ApplyMove won't do ANY validity checks.**
            // The return type is the MoveType enum. It holds one, or a combination, of these values: Invalid, Move, Capture, Castling, Promotion
            // Each valid move will always carry the 'Move' value. If it's also something else, it will carry both values (e.g. if the move is a capture, `type` will have the value MoveType.Move | MoveType.Capture).
            // MoveType is a flags enumeration. https://msdn.microsoft.com/en-us/library/ms229062%28v=vs.100%29.aspx
            // e4 is just a normal move, so `type` will just be MoveType.Move.
            Console.WriteLine("Move type: {0}", type);

            // When a move has been made, check the Status property. It will let you know if there is a special event: check, checkmate, stalemate ...
            GameStatus status = game.Status;
            Console.WriteLine("Special event? {0}", status.Event);
            // Here it just returns 'None' because nothing special happened.
            // GameStatus has two other properties: PlayerWhoCausedEvent (quite self-explanatory) and EventExplanation (used if Chess.NET needs to be more specific about an event, e.g. when it's a draw, explaining why).

            // Now it's black's turn.
            Console.WriteLine("It's this color's turn: {0}", game.WhoseTurn);

            // You can figure out all valid moves using GetValidMoves.
            IEnumerable<Move> validMoves = game.GetValidMoves(Player.Black);
            // Here it returns all valid moves for black, but you can also find all valid moves *from a certain position* by passing a Position instance as argument.
            Console.WriteLine("How many valid moves does black have? {0}", validMoves.Count());

            // It might happen that you don't really care about all valid moves, but just want to know if there are valid moves. Chess.NET also has a method for that:
            bool hasValidMoves = game.HasAnyValidMoves(Player.Black);
            // Again, you can also pass a Position instance here.
            Console.WriteLine("Black has any valid moves: {0}", hasValidMoves);

            // Congratulations! You have learned about the most important methods of Chess.NET. Enjoy using the library :)
            Console.ReadKey();
        }
예제 #2
0
        public override bool IsLegalMove(Move move, ChessGame game)
        {
            ChessUtility.ThrowIfNull(move, "move");
            ChessUtility.ThrowIfNull(game, "game");
            BoardPosition origin      = move.OriginalPosition;
            BoardPosition destination = move.NewPosition;

            BoardDistance posDelta = new BoardDistance(origin, destination);

            if (posDelta.X != 0 && posDelta.Y != 0)
            {
                return(false);
            }
            bool increasingRank = destination.Rank > origin.Rank;
            bool increasingFile = (int)destination.File > (int)origin.File;

            if (posDelta.X == 0)
            {
                int f = (int)origin.File;
                for (int r = origin.Rank + (increasingRank ? 1 : -1);
                     increasingRank?r <destination.Rank : r> destination.Rank;
                     r += increasingRank ? 1 : -1)
                {
                    if (game.GetPieceAt((ChessFile)f, r) != null)
                    {
                        return(false);
                    }
                }
            }
            else // (posDelta.DeltaY == 0)
            {
                int r = origin.Rank;
                for (int f = (int)origin.File + (increasingFile ? 1 : -1);
                     increasingFile?f <(int)destination.File : f> (int) destination.File;
                     f += increasingFile ? 1 : -1)
                {
                    if (game.GetPieceAt((ChessFile)f, r) != null)
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
예제 #3
0
        public static bool MoveIsValid(ChessBoard board, int startIndex, int endIndex)
        {
            var move = new Move(startIndex.GetChessDotNetPosition(), endIndex.GetChessDotNetPosition(), board.Cells[startIndex].IsBlack.ChessDotNetPlayer());

            var gameCreationData = new GameCreationData();

            for (var i = 0; i < 8; i++)
            {
                for (var j = 0; j < 8; j++)
                {
                    var cell = board.Cells[i * j];
                    gameCreationData.Board[i][j] = cell.Piece.Value.ChessDotNetPiece(cell.IsBlack);
                }
            }

            var game = new ChessDotNet.ChessGame(gameCreationData);

            return(game.IsValidMove(move));
        }
예제 #4
0
 /// <summary>
 /// 生成文字描述。
 /// </summary>
 public void GenerateFriendlyText()
 {
     var sb = new System.Text.StringBuilder();
     sb.Append(Piece.GetFriendlyName());
     sb.Append("从");
     sb.Append(OriginalPosition.ToString());
     sb.Append("到");
     sb.Append(NewPosition.ToString());
     if (IsCapture && CapturedPiece != null)
     {
         sb.Append(", 吃");
         sb.Append(CapturedPiece.GetFriendlyName());
     }
     if (Promotion.HasValue)
     {
         sb.Append(", 晋升为");
         sb.Append(ChessGame.OriginalMapPgnCharToPiece(Promotion.Value, Player).GetFriendlyName());
     }
     if (Castling.Equals(CastlingType.KingSide))
     {
         sb.Append(", 王翼易位");
     }
     if (Castling.Equals(CastlingType.QueenSide))
     {
         sb.Append(", 后翼易位");
     }
     if(IsEnpassant)
     {
         sb.Append(", 吃过路兵");
     }
     if (IsCheckmate.HasValue && IsCheckmate.Value)
     {
         sb.Append(", 将死");
     } else if (IsChecking.HasValue && IsChecking.Value)
     {
         sb.Append(", 将军");
     }
     this._storedFriendlyText = sb.ToString();
 }
예제 #5
0
        protected virtual bool IsInCheck(Player player)
        {
            List <Position> piecePositions = new List <Position>();
            Position        kingPos        = new Position(File.None, Rank.None);

            for (int i = 0; i < Board.Length; i++)
            {
                for (int j = 0; j < Board[i].Length; j++)
                {
                    ChessPiece curr = Board[i][j];
                    if (curr.Piece != Piece.None && curr.Player == Utilities.GetOpponentOf(player))
                    {
                        piecePositions.Add(new Position((File)j, (Rank)i));
                    }
                    else if (curr.Piece == Piece.King && curr.Player == player)
                    {
                        kingPos = new Position((File)j, (Rank)i);
                    }
                }
            }

            if (kingPos.File == File.None)
            {
                return(false);
            }

            ChessGame copy = new ChessGame(Board, Utilities.GetOpponentOf(player), false);

            for (int i = 0; i < piecePositions.Count; i++)
            {
                if (copy.IsValidMove(new Move(piecePositions[i], kingPos, Utilities.GetOpponentOf(player)), false))
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #6
0
        /// <summary>
        /// 将 SAN 字符串解析为 Move。
        /// </summary>
        /// <param name="moveInStr"></param>
        /// <param name="player"></param>
        /// <param name="game"></param>
        /// <returns></returns>
        public static Move ParseMove(string moveInStr, Player player, ChessGame game)
        {
            try
            {
                string move = moveInStr.TrimEnd('#', '?', '!', '+').Trim();

                Position origin      = null;
                Position destination = null;
                Piece    piece       = null;
                char?    promotion   = null;

                if (move.Length == 0)
                {
                    throw new PgnException("The length of Move string is zero.");
                }

                if (move.Length > 2)
                {
                    string possiblePromotionPiece = move.Substring(move.Length - 2).ToUpperInvariant();
                    if (possiblePromotionPiece[0] == '=')
                    {
                        promotion = possiblePromotionPiece[1];
                        move      = move.Remove(move.Length - 2, 2);
                    }
                }

                if (move.ToUpperInvariant() == "O-O")
                {
                    int r = player == Player.White ? 1 : 8;
                    origin      = new Position(File.E, r);
                    destination = new Position(File.G, r);
                    piece       = new King(player);
                }
                else if (move.ToUpperInvariant() == "O-O-O")
                {
                    int r = player == Player.White ? 1 : 8;
                    origin      = new Position(File.E, r);
                    destination = new Position(File.C, r);
                    piece       = new King(player);
                }

                if (piece == null)
                {
                    piece = game.MapPgnCharToPiece(move[0], player);
                }
                if (!(piece is Pawn))
                {
                    move = move.Remove(0, 1);
                }

                int  rankRestriction = -1;
                File fileRestriction = File.None;
                if (destination == null)
                {
                    if (move.Length == 0)
                    {
                        throw new PgnException("The position of Move is empty.");
                    }

                    if (move[0] == 'x')
                    {
                        move = move.Remove(0, 1);
                    }
                    else if (move.Length == 4 && move[1] == 'x')
                    {
                        move = move.Remove(1, 1);
                    }

                    if (move.Length == 2)
                    {
                        destination = new Position(move);
                    }
                    else if (move.Length == 3)
                    {
                        if (char.IsDigit(move[0]))
                        {
                            rankRestriction = int.Parse(move[0].ToString());
                        }
                        else
                        {
                            bool recognized = Enum.TryParse <File>(move[0].ToString(), true, out fileRestriction);
                            if (!recognized)
                            {
                                throw new PgnException("Invalid PGN: unrecognized origin file.");
                            }
                        }
                        destination = new Position(move.Remove(0, 1));
                    }
                    else if (move.Length == 4)
                    {
                        origin      = new Position(move.Substring(0, 2));
                        destination = new Position(move.Substring(2, 2));
                    }
                    else
                    {
                        throw new PgnException("Invalid PGN.");
                    }
                }

                Move m;
                if (origin != null)
                {
                    m = new Move(origin, destination, player, promotion);
                    if (game.IsValidMove(m))
                    {
                        return(m);
                    }
                    else
                    {
                        throw new PgnException("Invalid PGN: contains invalid moves.");
                    }
                }
                else
                {
                    Piece[][]   board      = game.GetBoard();
                    List <Move> validMoves = new List <Move>();
                    for (int r = 0; r < game.BoardHeight; r++)
                    {
                        if (rankRestriction != -1 && r != 8 - rankRestriction)
                        {
                            continue;
                        }
                        for (int f = 0; f < game.BoardWidth; f++)
                        {
                            if (fileRestriction != File.None && f != (int)fileRestriction)
                            {
                                continue;
                            }
                            if (board[r][f] != piece)
                            {
                                continue;
                            }
                            m = new Move(new Position((File)f, 8 - r), destination, player, promotion);
                            if (game.IsValidMove(m, true))
                            {
                                validMoves.Add(m);
                            }
                        }
                    }
                    if (validMoves.Count == 0)
                    {
                        throw new PgnException("Invalid PGN: contains invalid moves.");
                    }
                    if (validMoves.Count > 1)
                    {
                        throw new PgnException("Invalid PGN: contains ambiguous moves.");
                    }
                    return(validMoves[0]);
                }
            }
            catch (Exception e)
            {
                if (e is PgnException eP)
                {
                    throw eP;
                }
                else
                {
                    throw new PgnException(e.Message + Environment.NewLine + e.StackTrace);
                }
            }
        }
예제 #7
0
 public abstract ReadOnlyCollection<Move> GetValidMoves(Position from, bool returnIfAny, ChessGame game, Func<Move, bool> gameMoveValidator);
예제 #8
0
 public abstract bool IsValidMove(Move move, ChessGame game);
예제 #9
0
 public abstract ReadOnlyCollection <Move> GetLegalMoves(BoardPosition position, bool returnIfAny, ChessGame game, Func <Move, bool> gameMoveValidator);
예제 #10
0
 public abstract bool IsLegalMove(Move move, ChessGame game);
예제 #11
0
        public override ReadOnlyCollection <Move> GetLegalMoves(BoardPosition from, bool returnIfAny, ChessGame game, Func <Move, bool> gameMoveValidator)
        {
            ChessUtility.ThrowIfNull(from, "from");
            List <Move> validMoves = new List <Move>();
            ChessPiece  piece      = game.GetPieceAt(from);
            int         l0         = game.BoardHeight;
            int         l1         = game.BoardWidth;

            for (int i = -7; i < 8; i++)
            {
                if (i == 0)
                {
                    continue;
                }
                if (from.Rank + i > 0 && from.Rank + i <= l0)
                {
                    Move move = new Move(from, new BoardPosition(from.File, from.Rank + i), piece.Owner);
                    if (gameMoveValidator(move))
                    {
                        validMoves.Add(move);
                        if (returnIfAny)
                        {
                            return(new ReadOnlyCollection <Move>(validMoves));
                        }
                    }
                }
                if ((int)from.File + i > -1 && (int)from.File + i < l1)
                {
                    Move move = new Move(from, new BoardPosition(from.File + i, from.Rank), piece.Owner);
                    if (gameMoveValidator(move))
                    {
                        validMoves.Add(move);
                        if (returnIfAny)
                        {
                            return(new ReadOnlyCollection <Move>(validMoves));
                        }
                    }
                }
            }
            return(new ReadOnlyCollection <Move>(validMoves));
        }
예제 #12
0
파일: Piece.cs 프로젝트: ahmedbahaaeldin/MI
 public abstract bool IsValidMove(Move move, ChessGame game);
예제 #13
0
        /// <summary>
        /// 生成 SAN 字符串。
        /// </summary>
        /// <param name="gameBeforeTheMove"></param>
        /// <returns></returns>
        public string GenerateSANString(ChessGame gameBeforeTheMove)
        {
            string SANResult;
            if (Castling.Equals(CastlingType.KingSide))
            {
                SANResult = "O-O";
            }
            else if (Castling.Equals(CastlingType.QueenSide))
            {
                SANResult = "O-O-O";
            }
            else
            {
                var sb = new System.Text.StringBuilder();

                if (!(Piece is Pieces.Pawn))
                {
                    sb.Append(char.ToUpper(Piece.GetFenCharacter()));
                }

                Piece[][] board = gameBeforeTheMove.GetBoard();
                List<Move> validMoves = new List<Move>();
                for (int r = 0; r < 8; r++)
                {
                    for (int f = 0; f < 8; f++)
                    {
                        if (board[r][f] != Piece) continue;
                        Move m = new Move(new Position((File)f, 8 - r), this.NewPosition, this.Player, this.Promotion);
                        if (gameBeforeTheMove.IsValidMove(m))
                        {
                            validMoves.Add(m);
                        }
                    }
                }
                if (validMoves.Count == 0) throw new PgnException("This move " + this.ToString() + " is not valid for gameBeforeTheMove.");
                else if (validMoves.Count > 1)
                {
                    bool fileUnique = true;
                    bool rankUnique = true;
                    foreach (var move in validMoves)
                    {
                        if(!(move.OriginalPosition.Equals(this.OriginalPosition)))
                        {
                            if (move.OriginalPosition.File == this.OriginalPosition.File)
                            {
                                fileUnique = false;
                            }
                            if (move.OriginalPosition.Rank == this.OriginalPosition.Rank)
                            {
                                rankUnique = false;
                            }
                        }
                    }

                    if (fileUnique)
                        sb.Append((char)((int)'a' + (int)this.OriginalPosition.File));
                    else if (rankUnique)
                        sb.Append(this.OriginalPosition.Rank.ToString());
                    else
                    {
                        sb.Append((char)((int)'a' + (int)this.OriginalPosition.File));
                        sb.Append(this.OriginalPosition.Rank.ToString());
                    }
                }

                if (IsCapture)
                    sb.Append("x");

                sb.Append(this.NewPosition.ToString().ToLower());

                if (Promotion.HasValue)
                {
                    sb.Append("=");
                    sb.Append(Promotion.Value);
                }

                if (IsCheckmate.HasValue && IsCheckmate.Value)
                {
                    sb.Append("#");
                }
                else if (IsChecking.HasValue && IsChecking.Value)
                {
                    sb.Append("+");
                }

                SANResult = sb.ToString();
            }
            try
            {
                ChessDotNet.PgnMoveReader.ParseMove(SANResult, Player, gameBeforeTheMove);
            }
            catch (PgnException)
            {
                throw new System.ArgumentException("This move " + SANResult + " is not valid for gameBeforeTheMove.");
            }
            catch (System.ArgumentException)
            {
                throw new System.ArgumentException("This move " + SANResult + " is not valid for gameBeforeTheMove.");
            }
            this._storedSANString = SANResult;
            return SANResult;
        }
예제 #14
0
파일: Piece.cs 프로젝트: asibahi/Chess.NET
 public abstract ReadOnlyCollection <Move> GetValidMoves(Square from, bool returnIfAny, ChessGame game);
예제 #15
0
 public virtual bool WouldBeInCheckAfter(Move move, Player player)
 {
     ChessUtilities.ThrowIfNull(move, "move");
     GameCreationData gcd = new GameCreationData();
     gcd.Board = Board;
     gcd.CanWhiteCastleKingSide = CanWhiteCastleKingSide;
     gcd.CanWhiteCastleQueenSide = CanWhiteCastleQueenSide;
     gcd.CanBlackCastleKingSide = CanBlackCastleKingSide;
     gcd.CanBlackCastleQueenSide = CanBlackCastleQueenSide;
     gcd.EnPassant = null;
     if (_moves.Count > 0)
     {
         DetailedMove last = _moves.Last();
         if (last.Piece is Pawn && new PositionDistance(last.OriginalPosition, last.NewPosition).DistanceY == 2)
         {
             gcd.EnPassant = new Position(last.NewPosition.File, last.Player == Player.White ? 3 : 6);
         }
     }
     gcd.HalfMoveClock = _halfMoveClock;
     gcd.FullMoveNumber = _fullMoveNumber;
     ChessGame copy = new ChessGame(gcd);
     copy.ApplyMove(move, true);
     return copy.IsInCheck(player);
 }
예제 #16
0
        protected virtual bool IsInCheck(Player player)
        {
            List<Position> piecePositions = new List<Position>();
            Position kingPos = new Position(File.None, Rank.None);

            for (int i = 0; i < Board.Length; i++)
            {
                for (int j = 0; j < Board[i].Length; j++)
                {
                    ChessPiece curr = Board[i][j];
                    if (curr.Piece != Piece.None && curr.Player == Utilities.GetOpponentOf(player))
                    {
                        piecePositions.Add(new Position((File)j, (Rank)i));
                    }
                    else if (curr.Piece == Piece.King && curr.Player == player)
                    {
                        kingPos = new Position((File)j, (Rank)i);
                    }
                }
            }

            if (kingPos.File == File.None)
                return false;

            ChessGame copy = new ChessGame(Board, Utilities.GetOpponentOf(player), false);
            for (int i = 0; i < piecePositions.Count; i++)
            {
                if (copy.IsValidMove(new Move(piecePositions[i], kingPos, Utilities.GetOpponentOf(player)), false))
                {
                    return true;
                }
            }

            return false;
        }
예제 #17
0
 protected virtual bool WouldBeInCheckAfter(Move move, Player player)
 {
     Utilities.ThrowIfNull(move, "move");
     ChessGame copy = new ChessGame(Board, player, false);
     copy.ApplyMove(move, true, false);
     GameStatus status = copy.CalculateStatus(player, false);
     return status.Event == GameEvent.Check && status.PlayerWhoCausedEvent != player;
 }
예제 #18
0
파일: Piece.cs 프로젝트: ahmedbahaaeldin/MI
 public abstract ReadOnlyCollection <Move> GetValidMoves(Position from, bool returnIfAny, ChessGame game, Func <Move, bool> gameMoveValidator);