public ChessGame(GameCreationData data) { UseGameCreationData(data); }
public ChessGame(string fen) { GameCreationData data = FenStringToGameCreationData(fen); UseGameCreationData(data); }
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); }
protected virtual GameCreationData FenStringToGameCreationData(string fen) { Dictionary<char, Piece> fenMappings = FenMappings; string[] parts = fen.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (!AllowedFenPartsLength.Contains(parts.Length)) throw new ArgumentException("The FEN string has too much, or too few, parts."); Piece[][] board = new Piece[8][]; string[] rows = parts[0].Split('/'); if (rows.Length != 8) throw new ArgumentException("The board in the FEN string does not have 8 rows."); GameCreationData data = new GameCreationData(); for (int i = 0; i < 8; i++) { string row = rows[i]; Piece[] currentRow = new Piece[8] { null, null, null, null, null, null, null, null }; int j = 0; foreach (char c in row) { if (char.IsDigit(c)) { j += (int)char.GetNumericValue(c); continue; } if (!fenMappings.ContainsKey(c)) throw new ArgumentException("The FEN string contains an unknown piece."); currentRow[j] = fenMappings[c]; j++; } if (j != 8) { throw new ArgumentException("Not enough pieces provided for a row in the FEN string."); } board[i] = currentRow; } data.Board = board; if (parts[1] == "w") { data.WhoseTurn = Player.White; } else if (parts[1] == "b") { data.WhoseTurn = Player.Black; } else { throw new ArgumentException("Expected `w` or `b` for the active player in the FEN string."); } if (parts[2].Contains('K')) data.CanWhiteCastleKingSide = true; else data.CanWhiteCastleKingSide = false; if (parts[2].Contains('Q')) data.CanWhiteCastleQueenSide = true; else data.CanWhiteCastleQueenSide = false; if (parts[2].Contains('k')) data.CanBlackCastleKingSide = true; else data.CanBlackCastleKingSide = false; if (parts[2].Contains('q')) data.CanBlackCastleQueenSide = true; else data.CanBlackCastleQueenSide = false; if (parts[3] == "-") data.EnPassant = null; else { Position ep = new Position(parts[3]); if ((data.WhoseTurn == Player.White && (ep.Rank != 6 || !(data.Board[3][(int)ep.File] is Pawn))) || (data.WhoseTurn == Player.Black && (ep.Rank != 3 || !(data.Board[4][(int)ep.File] is Pawn)))) { throw new ArgumentException("Invalid en passant field in FEN."); } data.EnPassant = ep; } int halfmoveClock; if (int.TryParse(parts[4], out halfmoveClock)) { data.HalfMoveClock = halfmoveClock; } else { throw new ArgumentException("Halfmove clock in FEN is invalid."); } int fullMoveNumber; if (int.TryParse(parts[5], out fullMoveNumber)) { data.FullMoveNumber = fullMoveNumber; } else { throw new ArgumentException("Fullmove number in FEN is invalid."); } return data; }
protected virtual void UseGameCreationData(GameCreationData data) { Board = CloneBoard(data.Board); WhoseTurn = data.WhoseTurn; Piece e1 = GetPieceAt(File.E, 1); Piece e8 = GetPieceAt(File.E, 8); Piece a1 = GetPieceAt(File.A, 1); Piece h1 = GetPieceAt(File.H, 1); Piece a8 = GetPieceAt(File.A, 8); Piece h8 = GetPieceAt(File.H, 8); CanBlackCastleKingSide = CanBlackCastleQueenSide = CanWhiteCastleKingSide = CanWhiteCastleQueenSide = CastlingCanBeLegal; if (CastlingCanBeLegal) { if (!(e1 is King) || e1.Owner != Player.White) CanWhiteCastleKingSide = CanWhiteCastleQueenSide = false; if (!(e8 is King) || e8.Owner != Player.Black) CanBlackCastleKingSide = CanBlackCastleQueenSide = false; if (!(a1 is Rook) || a1.Owner != Player.White || !data.CanWhiteCastleQueenSide) CanWhiteCastleQueenSide = false; if (!(h1 is Rook) || h1.Owner != Player.White || !data.CanWhiteCastleKingSide) CanWhiteCastleKingSide = false; if (!(a8 is Rook) || a8.Owner != Player.Black || !data.CanBlackCastleQueenSide) CanBlackCastleQueenSide = false; if (!(h8 is Rook) || h8.Owner != Player.Black || !data.CanBlackCastleKingSide) CanBlackCastleKingSide = false; } if (data.EnPassant != null) { DetailedMove latestMove = new DetailedMove(new Move(new Position(data.EnPassant.File, data.WhoseTurn == Player.White ? 7 : 2), new Position(data.EnPassant.File, data.WhoseTurn == Player.White ? 5 : 4), ChessUtilities.GetOpponentOf(data.WhoseTurn)), new Pawn(ChessUtilities.GetOpponentOf(data.WhoseTurn)), false, CastlingType.None); _moves.Add(latestMove); } _halfMoveClock = data.HalfMoveClock; _fullMoveNumber = data.FullMoveNumber; }