Beispiel #1
0
        public static Board Parse(string board)
        {
            var rows = board.Split('\r', '\n').Where(r => !string.IsNullOrEmpty(r)).ToArray();

            if (rows.Length != 8)
            {
                throw new ArgumentException($"Should be 8 rows! (got {rows.Length})");
            }
            var boardRows = new List <Square[]>();

            for (int rowIndex = 0; rowIndex < 8; rowIndex++)
            {
                var row      = rows[rowIndex];
                var boardRow = new List <Square>();
                if (row.Length != (8 * 3) - 1)
                {
                    throw new ArgumentException($"Rows must be 23 chars. Row {rowIndex} was {row.Length}");
                }
                for (int columnIndex = 0; columnIndex < 8; columnIndex++)
                {
                    string pieceString = row.Substring(columnIndex * 3, 2);
                    var    square      = new Square(
                        SquareReference.FromRowColumn(rowIndex, columnIndex),
                        ParsePiece(pieceString)
                        );
                    boardRow.Add(square);
                }
                boardRows.Add(boardRow.ToArray());
            }
            return(new Board {
                Squares = boardRows.ToArray()
            });
        }
Beispiel #2
0
        public static IEnumerable <SquareReference> MovesUntilPiece(
            this Board board,
            SquareReference start,
            int rowDelta,
            int columnDelta,
            Color opponentColor)
        {
            SquareReference?move = start;

            while (true)
            {
                move = move.Value.Move(rowDelta, columnDelta);
                if (move == null)
                {
                    yield break;
                }
                var piece = board[move.Value].Piece;
                if (piece.Color == opponentColor)
                {
                    yield return(move.Value);

                    yield break;
                }
                else if (piece.Color == Color.Empty)
                {
                    yield return(move.Value);
                    // yield and continue
                }
                else
                {
                    // own color
                    yield break;
                }
            }
        }
Beispiel #3
0
 public Move(DateTime moveTimeUtc, Piece piece, SquareReference start, SquareReference end, Piece capturedPiece)
 {
     MoveTimeUtc   = moveTimeUtc;
     Piece         = piece;
     Start         = start;
     End           = end;
     CapturedPiece = capturedPiece;
 }
Beispiel #4
0
        public Board MovePiece(SquareReference from, SquareReference to)
        {
            var newBoard = Clone();
            var piece    = Squares[from.Row][from.Column].Piece;

            newBoard.Squares[from.Row][from.Column].Piece = Piece.Empty;
            newBoard.Squares[to.Row][to.Column].Piece     = piece;
            return(newBoard);
        }
Beispiel #5
0
        public static SquareReference?Move(this SquareReference start, int rowDelta, int columnDelta)
        {
            int newRow    = start.Row + rowDelta;
            int newColumn = start.Column + columnDelta;

            if (newRow < 0 || newRow > 7 ||
                newColumn < 0 || newColumn > 7)
            {
                return(null);
            }
            return(SquareReference.FromRowColumn(newRow, newColumn));
        }
Beispiel #6
0
 public static Board CreateEmptyBoard()
 {
     return(new Board
     {
         Squares = new Square[8][]
         {
             Enumerable.Range(0, 8).Select(i => new Square(SquareReference.FromRowColumn(0, i), Piece.Empty)).ToArray(),
             Enumerable.Range(0, 8).Select(i => new Square(SquareReference.FromRowColumn(1, i), Piece.Empty)).ToArray(),
             Enumerable.Range(0, 8).Select(i => new Square(SquareReference.FromRowColumn(2, i), Piece.Empty)).ToArray(),
             Enumerable.Range(0, 8).Select(i => new Square(SquareReference.FromRowColumn(3, i), Piece.Empty)).ToArray(),
             Enumerable.Range(0, 8).Select(i => new Square(SquareReference.FromRowColumn(4, i), Piece.Empty)).ToArray(),
             Enumerable.Range(0, 8).Select(i => new Square(SquareReference.FromRowColumn(5, i), Piece.Empty)).ToArray(),
             Enumerable.Range(0, 8).Select(i => new Square(SquareReference.FromRowColumn(6, i), Piece.Empty)).ToArray(),
             Enumerable.Range(0, 8).Select(i => new Square(SquareReference.FromRowColumn(7, i), Piece.Empty)).ToArray(),
         }
     });
 }
Beispiel #7
0
 public static Board CreateStartingBoard()
 {
     return(new Board
     {
         Squares = new Square[8][]
         {
             (new [] { 2, 3, 4, 5, 6, 4, 3, 2 })
             .Select(
                 (i, index) => new Square(
                     SquareReference.FromRowColumn(0, index),
                     new Piece(Color.Black, (PieceType)i)
                     )
                 ).ToArray(),
             Enumerable.Range(0, 8)
             .Select(
                 i => new Square(
                     SquareReference.FromRowColumn(1, i),
                     new Piece(Color.Black, PieceType.Pawn)
                     )
                 ).ToArray(),
             Enumerable.Range(0, 8).Select(i => new Square(SquareReference.FromRowColumn(2, i), Piece.Empty)).ToArray(),
             Enumerable.Range(0, 8).Select(i => new Square(SquareReference.FromRowColumn(3, i), Piece.Empty)).ToArray(),
             Enumerable.Range(0, 8).Select(i => new Square(SquareReference.FromRowColumn(4, i), Piece.Empty)).ToArray(),
             Enumerable.Range(0, 8).Select(i => new Square(SquareReference.FromRowColumn(5, i), Piece.Empty)).ToArray(),
             Enumerable.Range(0, 8)
             .Select(
                 i => new Square(
                     SquareReference.FromRowColumn(6, i),
                     new Piece(Color.White, PieceType.Pawn)
                     )
                 ).ToArray(),
             (new [] { 2, 3, 4, 5, 6, 4, 3, 2 })
             .Select(
                 (i, index) => new Square(
                     SquareReference.FromRowColumn(7, index),
                     new Piece(Color.White, (PieceType)i)
                     )
                 ).ToArray()
         }
     });
 }
Beispiel #8
0
        public IEnumerable <SquareReference> GetAvailableMoves(SquareReference from)
        {
            var initialMoves = GetAvailableMoves_NoCheckTest(this, from);

            var square = Board[from];
            var piece  = square.Piece;


            // filter out moves that result in check
            // brute force approach ;-)
            // for each move, check whether there are any moves for any opponent piece after that
            // which would end on the current player's king's square
            // if so then we have a move that puts the player into check, so filter out
            var nonCheckMoves = initialMoves.Where(move =>
            {
                var newGame = MakeMove_Internal(from: square.Reference, to: move, suppressValidityCheck: true);

                return(!IsInCheck(newGame, piece.Color));
            });

            return(nonCheckMoves);
        }
Beispiel #9
0
        private Game MakeMove_Internal(SquareReference from, SquareReference to, bool suppressValidityCheck)
        {
            if (!suppressValidityCheck) // GetAvailable moves calls this, so this flag avoids StackOverflowException ;-)
            {
                if (Board[from].Piece.Color != CurrentTurn ||
                    !GetAvailableMoves(from).Contains(to))
                {
                    throw new ArgumentException("Invalid move");
                }
            }

            var    capturedPiece = Board[to].Piece;
            Square square        = Board[from];
            var    newGame       = new Game(
                id: Id,
                currentTurn: (CurrentTurn == Color.Black) ? Color.White : Color.Black,
                board: Board.MovePiece(from, to),
                moves: _moves.Concat(new[] { new Move(DateTime.UtcNow, square.Piece, from, to, capturedPiece) }).ToList()
                );

            return(newGame);
            // TODO - add a flag for whether the current player is in check
        }
Beispiel #10
0
 public Game MakeMove(SquareReference from, SquareReference to)
 {
     return(MakeMove_Internal(from, to, suppressValidityCheck: false));
 }
Beispiel #11
0
        private IEnumerable <SquareReference> GetAvailableMoves_NoCheckTest(Game game, SquareReference from)
        {
            var square    = game.Board[from];
            var pieceType = square.Piece.PieceType;

            switch (pieceType)
            {
            case PieceType.Pawn:
                return(GetAvailableMoves_Pawn(game, square));

            case PieceType.Rook:
                return(GetAvailableMoves_Rook(game, square));

            case PieceType.Knight:
                return(GetAvailableMoves_Knight(game, square));

            case PieceType.Bishop:
                return(GetAvailableMoves_Bishop(game, square));

            case PieceType.Queen:
                return(GetAvailableMoves_Queen(game, square));

            case PieceType.King:
                return(GetAvailableMoves_King(game, square));

            default:
                throw new InvalidOperationException($"Unhandled piece type!! {pieceType}");
            }
        }
Beispiel #12
0
 }                                // TODO - should we make this immutable?
 public Square(SquareReference reference, Piece piece)
 {
     Reference = reference;
     Piece     = piece;
 }
Beispiel #13
0
 public Square this[SquareReference reference]
 {
     get { return(Squares[reference.Row][reference.Column]); }
 }