/* * Create an ASCII representation of a position */ public static String asciiBoard(Position position) { StringBuilder boardRepresentation = new StringBuilder(400); String newLine = Environment.NewLine; boardRepresentation.Append(" +----+----+----+----+----+----+----+----+"); boardRepresentation.Append(newLine); for (int rank = 7; rank >= 0; rank--) { boardRepresentation.Append(" |"); for (int file = 0; file < 8; file++) { boardRepresentation.Append(" "); PieceType piece = position.getPiece(Position.getSquare(file, rank)); if (piece == PieceType.Empty) { Boolean isDark = Position.darkSquare(file, rank); boardRepresentation.Append(isDark ? ".. |" : " |"); } else { //A black piece has prefaced with a * boardRepresentation.Append(((int)piece < 6) ? ' ' : '*'); String pieceName = "" + piece; boardRepresentation.Append(pieceName); boardRepresentation.Append(" |"); } } boardRepresentation.Append(newLine); boardRepresentation.Append(" +----+----+----+----+----+----+----+----+"); boardRepresentation.Append(newLine); } return boardRepresentation.ToString(); }
/* * Return true if the side to move is in check */ public static Boolean inCheck(Position position) { int kingSquare = position.getKingSquare(position.whiteMove); if (kingSquare < 0) { return false; } return squareAttacked(position, kingSquare); }
public void TestEmptyPosition() { //arrange String emptyFEN = "8/8/8/8/8/8/8/8 w - - 0 1"; //act Position empty = new Position(); //assert Assert.AreEqual(emptyFEN, FENConverter.convertPositionToFEN(empty)); }
public static Position PawnGamePosition() { Position position = new Position(); String pawnGamePosition = "4k3/pppppppp/8/8/8/8/PPPPPPPP/4K3 w KQkq - 0 1"; position = FENConverter.convertFENToPosition(pawnGamePosition); return position; }
/* * Initialise board to a given position */ public Position(Position position) { pieceLayout = position.pieceLayout; whiteMove = position.whiteMove; castleMask = position.castleMask; epSquare = position.epSquare; halfMoveClock = position.halfMoveClock; fullMoveCounter = position.fullMoveCounter; wKingSquare = position.wKingSquare; bKingSquare = position.bKingSquare; sameActiveColor = position.sameActiveColor; }
/* * Returns true if a move is valid for a given position */ public static Boolean isMoveValid(Move move, Position position) { if (move == null) { return false; } ArrayList moves = new MoveGenerator().legalMoves(position); foreach (Move listMove in moves) { //Move is only valid if it appears in legal moves list if (move.Equals(listMove)) { return true; } } return false; }
/* * Removes illegal moves from the given move list * The move list contains psuedo-legal moves * This removes the moves that don't defend from check positions */ public static ArrayList removeIllegalMoves(Position position, ArrayList moveList) { ArrayList finalList = new ArrayList(); UnMakeInfo moveInfo = new UnMakeInfo(); int moveListCount = moveList.Count; for (int i = 0; i < moveListCount; i++) { Move move = (Move)moveList[i]; position.makeMove(move, moveInfo); position.setWhiteMove(!position.whiteMove); if (!inCheck(position)) { finalList.Add(move); } position.setWhiteMove(!position.whiteMove); position.unMakeMove(move, moveInfo); } return finalList; }
/* * Returns true if a move results in a caputre for a given * position */ public static Boolean isMoveCapture(Move move, Position position) { if (position.getPiece(move.destination) == PieceType.Empty) { //Deal with En Passant capture PieceType piece = position.getPiece(move.origin); if ((piece == (position.whiteMove ? PieceType.P : PieceType.p)) && (move.destination == position.getEpSquare())) { return true; } else { return false; } } else { return true; } }
public ParserError(int resourceID) : base("") { this.pos = null; this.resourceID = resourceID; }
public ParserError(String msg, Position pos) : base(msg) { this.pos = pos; }
public ParserError(String msg) : base(msg) { this.pos = null; }
/* * Check if there is an attacking piece in a given direction starting from * a given square. The direction is given by delta * @param maxSteps Max steps until reaching a border, Set to 1 for non-sliding pieces * Returns the first piece in the given direction, or Empty if there is no piece * in that direction */ private static PieceType checkDirection(Position position, int square, int maxSteps, int delta) { while (maxSteps > 0) { square += delta; PieceType piece = position.getPiece(square); if (piece != PieceType.Empty) { return piece; } maxSteps--; } return PieceType.Empty; }
/* * Return true if a square is attacked by the opposite side */ public static Boolean squareAttacked(Position position, int square) { int file = Position.getFile(square); int rank = Position.getRank(square); Boolean isWhiteMove = position.whiteMove; PieceType opppositeQueen = isWhiteMove ? PieceType.q : PieceType.Q; PieceType opppositeRook = isWhiteMove ? PieceType.r : PieceType.R; PieceType opppositeBishop = isWhiteMove ? PieceType.b : PieceType.B; PieceType opppositeKnight = isWhiteMove ? PieceType.n : PieceType.N; PieceType piece; if (rank > 0) { piece = checkDirection(position, square, rank, -8); if ((piece == opppositeQueen) || (piece == opppositeRook)) return true; piece = checkDirection(position, square, Math.Min(file, rank), -9); if ((piece == opppositeQueen) || (piece == opppositeBishop)) return true; piece = checkDirection(position, square, Math.Min(7 - file, rank), -7); if ((piece == opppositeQueen) || (piece == opppositeBishop)) return true; if (file > 1) { piece = checkDirection(position, square, 1, -10); if (piece == opppositeKnight) return true; } if (file > 0 && rank > 1) { piece = checkDirection(position, square, 1, -17); if (piece == opppositeKnight) return true; } if (file < 7 && rank > 1) { piece = checkDirection(position, square, 1, -15); if (piece == opppositeKnight) return true; } if (file < 6) { piece = checkDirection(position, square, 1, -6); if (piece == opppositeKnight) return true; } if (!isWhiteMove) { if (file < 7 && rank > 1) { piece = checkDirection(position, square, 1, -7); if (piece == PieceType.P) return true; } if (file > 0 && rank > 1) { piece = checkDirection(position, square, 1, -9); if (piece == PieceType.P) return true; } } } if (rank < 7) { piece = checkDirection(position, square, 7 - rank, 8); if ((piece == opppositeQueen) || (piece == opppositeRook)) return true; piece = checkDirection(position, square, Math.Min(7 - file, 7 - rank), 9); if ((piece == opppositeQueen) || (piece == opppositeBishop)) return true; piece = checkDirection(position, square, Math.Min(file, 7 - rank), 7); if ((piece == opppositeQueen) || (piece == opppositeBishop)) return true; if (rank < 6) { piece = checkDirection(position, square, 1, 10); if (piece == opppositeKnight) return true; } if (file < 7 && rank < 6) { piece = checkDirection(position, square, 1, 17); if (piece == opppositeKnight) return true; } if (file > 0 && rank < 6) { piece = checkDirection(position, square, 1, 15); if (piece == opppositeKnight) return true; } if (file > 1) { piece = checkDirection(position, square, 1, 6); if (piece == opppositeKnight) return true; } if (isWhiteMove) { if (file < 7 && rank < 6) { piece = checkDirection(position, square, 1, 9); if (piece == PieceType.p) return true; } if (file > 0 && rank < 6) { piece = checkDirection(position, square, 1, 7); if (piece == PieceType.p) return true; } } } piece = checkDirection(position, square, 7 - file, 1); if ((piece == opppositeQueen) || (piece == opppositeRook)) return true; piece = checkDirection(position, square, file, -1); if ((piece == opppositeQueen) || (piece == opppositeRook)) return true; int opppositeKingSquare = position.getKingSquare(!isWhiteMove); if (opppositeKingSquare >= 0) { int oFile = Position.getFile(opppositeKingSquare); int oRank = Position.getRank(opppositeKingSquare); if ((Math.Abs(file - oFile) <= 1) && (Math.Abs(rank - oRank) <= 1)) { return true; } } return false; }
/* * Converts a UCI move string (long algebraic notation) into * a move object */ public static Move moveStringToObject(String uci, Position position) { return moveStringToObject(uci, position, null); }
/* * Converts a move object into a UCI move string (long algebraic * notation) */ public static String moveObjectToString(Move move, Position position) { return moveObjectToString(move, position, null); }
/* * Convert a piece placement string to a position object * This does not have to adhere to the strict rules of how * many pieces a player must have. i.e.(player may have no king) * This is primarily used for testing purposes, as well as tutorial * scenarios. */ public static Position convertPiecePlacementToPosition(String fen) { Position position = new Position(); String[] terms = fen.Split(' '); if (terms.Length < 2) { System.Console.WriteLine("Too few terms"); } for (int i = 0; i < terms.Length; i++) { terms[i] = terms[i].Trim(); } //Piece placement int rank = 7; int file = 0; for (int i = 0; i < terms[0].Length; i++) { char c = (char)terms[0].ToCharArray().GetValue(i); switch (c) { case '1': file += 1; break; case '2': file += 2; break; case '3': file += 3; break; case '4': file += 4; break; case '5': file += 5; break; case '6': file += 6; break; case '7': file += 7; break; case '8': file += 8; break; case '/': rank--; file = 0; break; case 'P': position.setPiece(Position.getSquare(file, rank), PieceType.P); file++; break; case 'N': position.setPiece(Position.getSquare(file, rank), PieceType.N); file++; break; case 'B': position.setPiece(Position.getSquare(file, rank), PieceType.B); file++; break; case 'R': position.setPiece(Position.getSquare(file, rank), PieceType.R); file++; break; case 'Q': position.setPiece(Position.getSquare(file, rank), PieceType.Q); file++; break; case 'K': position.setPiece(Position.getSquare(file, rank), PieceType.K); file++; break; case 'p': position.setPiece(Position.getSquare(file, rank), PieceType.p); file++; break; case 'n': position.setPiece(Position.getSquare(file, rank), PieceType.n); file++; break; case 'b': position.setPiece(Position.getSquare(file, rank), PieceType.b); file++; break; case 'r': position.setPiece(Position.getSquare(file, rank), PieceType.r); file++; break; case 'q': position.setPiece(Position.getSquare(file, rank), PieceType.q); file++; break; case 'k': position.setPiece(Position.getSquare(file, rank), PieceType.k); file++; break; default: throw new ParserError("Invalid Piece", position); } } //Active Colour if (terms[1].Length > 0) { Boolean whiteToMove; char c = (char)terms[1].ToCharArray().GetValue(0); switch (c) { case 'w': whiteToMove = true; break; case 'b': whiteToMove = false; break; default: throw new ParserError("Invalid Active Colour", position); } position.setWhiteMove(whiteToMove); } else { throw new ParserError("Invalid Active Colour", position); } //Castling Rights int castleMask = 0; if (terms.Length > 2) { for (int i = 0; i < terms[2].Length; i++) { char c = (char)terms[2].ToCharArray().GetValue(i); switch (c) { case 'K': castleMask |= (1 << Position.H1_CASTLE); break; case 'Q': castleMask |= (1 << Position.A1_CASTLE); break; case 'k': castleMask |= (1 << Position.H8_CASTLE); break; case 'q': castleMask |= (1 << Position.A8_CASTLE); break; case '-': break; default: throw new ParserError("Invalid castling flags", position); } } } position.setCastleMask(castleMask); removeInvalidCastleFlags(position); //En Passant Target Square if (terms.Length > 3) { String epString = terms[3]; if (!epString.Equals("-")) { if (epString.Length < 2) { throw new ParserError("Invalid En Passent Square", position); } position.setEpSquare(getSquare(epString)); } } try { //Halfmove Clock if (terms.Length > 4) { position.halfMoveClock = Convert.ToInt32(terms[4]); } //Full Move Counter if (terms.Length > 5) { position.fullMoveCounter = Convert.ToInt32(terms[5]); } } catch (ArgumentException ae) { //Ignore errors here since fields are optional Console.WriteLine(ae.ToString()); } fixupEPSquare(position); return position; }
/* * Return a Forsyth-Edwards Notation string corresponding to a Position object */ public static String convertPositionToFEN(Position position) { StringBuilder feNotation = new StringBuilder(); //Piece placement for (int rank = 7; rank >= 0; rank--) { int emptySquares = 0; for (int file = 0; file < 8; file++) { PieceType piece = position.getPiece(Position.getSquare(file, rank)); if (piece == PieceType.Empty) { emptySquares++; } else { if (emptySquares > 0) { feNotation.Append(emptySquares); emptySquares = 0; } switch (piece) { case PieceType.K: feNotation.Append('K'); break; case PieceType.Q: feNotation.Append('Q'); break; case PieceType.R: feNotation.Append('R'); break; case PieceType.B: feNotation.Append('B'); break; case PieceType.N: feNotation.Append('N'); break; case PieceType.P: feNotation.Append('P'); break; case PieceType.k: feNotation.Append('k'); break; case PieceType.q: feNotation.Append('q'); break; case PieceType.r: feNotation.Append('r'); break; case PieceType.b: feNotation.Append('b'); break; case PieceType.n: feNotation.Append('n'); break; case PieceType.p: feNotation.Append('p'); break; default: throw new ParserError("Error creating FEN String"); } } } if (emptySquares > 0) { feNotation.Append(emptySquares); } if (rank > 0) { feNotation.Append("/"); } } //Active Colour feNotation.Append(position.whiteMove ? " w " : " b "); //Castling Rights Boolean anyCastle = false; if (position.h1Castle()) { feNotation.Append('K'); anyCastle = true; } if (position.a1Castle()) { feNotation.Append('Q'); anyCastle = true; } if (position.h8Castle()) { feNotation.Append('k'); anyCastle = true; } if (position.a8Castle()) { feNotation.Append('q'); anyCastle = true; } if (!anyCastle) { feNotation.Append('-'); } //En Passant Target Square { feNotation.Append(" "); if (position.getEpSquare() >= 0) { int file = Position.getFile(position.getEpSquare()); int rank = Position.getRank(position.getEpSquare()); feNotation.Append((char)(file + 'a')); feNotation.Append((char)(rank + '1')); } else { feNotation.Append('-'); } } //Move Counters feNotation.Append(' '); feNotation.Append(position.halfMoveClock); feNotation.Append(' '); feNotation.Append(position.fullMoveCounter); return feNotation.ToString(); }
public void StartPosition() { currentPosition = FENConverter.convertPiecePlacementToPosition(FENConverter.startPosition); }
public void ClearBoard() { currentPosition = FENConverter.convertPiecePlacementToPosition(FENConverter.emptyPosition); }
public TutorialBase() { currentPosition = FENConverter.convertPiecePlacementToPosition(FENConverter.emptyPosition); }
public ParserError(int resourceID, Position pos) : base("") { this.pos = pos; this.resourceID = resourceID; }
/* * Add all moves from a given square in direction delta * @param maxSteps Max steps until reaching a border, Set to 1 for non-sliding pieces * Returns True if the enemy king could be captured, false otherwise */ private Boolean addDirection(ArrayList moveList, Position position, int square, int maxSteps, int delta) { int destination = square; Boolean whiteToMove = position.whiteMove; PieceType opppositeKing = (whiteToMove ? PieceType.k : PieceType.K); while (maxSteps > 0) { destination += delta; PieceType piece = position.getPiece(destination); if (piece == PieceType.Empty) { moveList.Add(getMoveObject(square, destination, PieceType.Empty)); } else { //check if piece is white if (((int)piece < 6) != whiteToMove) { if (piece == opppositeKing) { returnMoveList(moveList); moveList = getMoveListObject(); moveList.Add(getMoveObject(square, destination, PieceType.Empty)); return true; } else { moveList.Add(getMoveObject(square, destination, PieceType.Empty)); } } break; } maxSteps--; } return false; }
private void GameInit() { currentPosition = FENConverter.convertFENToPosition(FENConverter.startPosition); unMakeInfo = new UnMakeInfo(); gameFinished = false; undoMove = false; }
/* * Set a given piece in a given square */ private static void setPieceSafely(Position position, int file, int rank, PieceType piece) { if (rank < 0) throw new ParserError("Too many ranks"); if (file > 7) throw new ParserError("Too many columns"); if ((piece == PieceType.P) || (piece == PieceType.p)) { if ((rank == 0) || (rank == 7)) { throw new ParserError("Pawn of first or last rank"); } } position.setPiece(Position.getSquare(file, rank), piece); }
/* * Converts a UCI move string (long algebraic notation into * a move object, a list of moves can be supplied to search * through. */ public static Move moveStringToObject(String moveString, Position position, ArrayList moves) { if (moveString.Equals("--")) { return new Move(0, 0, 0); } moveString = moveString.Replace("=", ""); moveString = moveString.Replace("\\+", ""); moveString = moveString.Replace("#", ""); Boolean whiteToMove = position.whiteMove; MoveComposition moveComp = new MoveComposition(); Boolean capture = false; if (moveString.Equals("O-O") || moveString.Equals("0-0") || moveString.Equals("o-o")) { moveComp.piece = whiteToMove ? PieceType.K : PieceType.k; moveComp.originFile = 4; moveComp.destinationFile = 6; moveComp.originRank = moveComp.destinationRank = whiteToMove ? 0 : 7; moveComp.promotionPiece = PieceType.Empty; } else if (moveString.Equals("O-O-O") || moveString.Equals("0-0-0") || moveString.Equals("o-o-o")) { moveComp.piece = whiteToMove ? PieceType.K : PieceType.k; moveComp.originFile = 4; moveComp.destinationFile = 2; moveComp.originRank = moveComp.destinationRank = whiteToMove ? 0 : 7; moveComp.promotionPiece = PieceType.Empty; } else { Boolean attackToSquare = false; for (int i = 0; i < moveString.Length; i++) { char c = moveString[i]; if (i == 0) { PieceType piece = charToPieceType(c); if (piece != PieceType.Empty) { moveComp.piece = piece; continue; } } int tempFile = c - 'a'; if ((tempFile >= 0) && (tempFile < 8)) { if (attackToSquare || (moveComp.originFile >= 0)) { moveComp.destinationFile = tempFile; } else { moveComp.originFile = tempFile; } } int tempRank = c - '1'; if ((tempRank >= 0) && (tempFile < 8)) { if (attackToSquare || (moveComp.originRank >= 0)) { moveComp.destinationRank = tempRank; } else { moveComp.originRank = tempRank; } } if ((c == 'x') || (c == '-')) { attackToSquare = true; if (c == 'x') { capture = true; } } if (i == moveString.Length - 1) { PieceType promotionPiece = charToPieceType(c); if (promotionPiece != PieceType.Empty) { moveComp.promotionPiece = promotionPiece; } } } if ((moveComp.originFile >= 0) && (moveComp.destinationFile < 0)) { moveComp.destinationFile = moveComp.originFile; moveComp.originFile = -1; } if ((moveComp.originRank >= 0) && (moveComp.destinationRank < 0)) { moveComp.destinationRank = moveComp.originRank; moveComp.originFile = -1; } if (moveComp.piece == PieceType.Empty) { Boolean haveAll = (moveComp.originFile >= 0) && (moveComp.destinationFile >= 0) && (moveComp.originRank >= 0) && (moveComp.destinationRank >= 0); if (!haveAll) { moveComp.piece = whiteToMove ? PieceType.P : PieceType.p; } } } if (moves == null) { moves = MoveGenerator.mgInstance.legalMoves(position); } ArrayList matches = new ArrayList(2); foreach (Move listMove in moves) { PieceType piece = position.getPiece(listMove.origin); Boolean match = true; if ((moveComp.piece >= 0) && (moveComp.piece != piece)) { match = false; } if ((moveComp.originFile >= 0) && (moveComp.originFile != Position.getFile(listMove.origin))) { match = false; } if ((moveComp.originRank >= 0) && (moveComp.originRank != Position.getRank(listMove.origin))) { match = false; } if ((moveComp.destinationFile >= 0) && (moveComp.destinationFile != Position.getFile(listMove.destination))) { match = false; } if ((moveComp.destinationRank >= 0) && (moveComp.destinationRank != Position.getRank(listMove.destination))) { match = false; } if ((moveComp.promotionPiece >= 0) && (moveComp.promotionPiece != listMove.promoteTo)) { match = false; } if (match) { matches.Add(listMove); } } int numMatches = matches.Count; if (numMatches == 0) { return null; } else if (numMatches == 1) { return (Move)matches[0]; } if (!capture) { return null; } Move move = null; foreach (Move listMove in matches) { PieceType capturedPiece = position.getPiece(listMove.destination); if (capturedPiece != PieceType.Empty) { if (move == null) { move = listMove; } else { return null; } } } return move; }
/* * Parse a FEN string and return a position object */ public static Position convertFENToPosition(String fen) { Position position = new Position(); String[] terms = fen.Split(' '); if (terms.Length < 2) { System.Console.WriteLine("Too few terms"); } for (int i = 0; i < terms.Length; i++) { terms[i] = terms[i].Trim(); } //Piece placement int rank = 7; int file = 0; for (int i = 0; i < terms[0].Length; i++) { char c = (char)terms[0].ToCharArray().GetValue(i); switch (c) { case '1': file += 1; break; case '2': file += 2; break; case '3': file += 3; break; case '4': file += 4; break; case '5': file += 5; break; case '6': file += 6; break; case '7': file += 7; break; case '8': file += 8; break; case '/': rank--; file = 0; break; case 'P': setPieceSafely(position, file, rank, PieceType.P); file++; break; case 'N': setPieceSafely(position, file, rank, PieceType.N); file++; break; case 'B': setPieceSafely(position, file, rank, PieceType.B); file++; break; case 'R': setPieceSafely(position, file, rank, PieceType.R); file++; break; case 'Q': setPieceSafely(position, file, rank, PieceType.Q); file++; break; case 'K': setPieceSafely(position, file, rank, PieceType.K); file++; break; case 'p': setPieceSafely(position, file, rank, PieceType.p); file++; break; case 'n': setPieceSafely(position, file, rank, PieceType.n); file++; break; case 'b': setPieceSafely(position, file, rank, PieceType.b); file++; break; case 'r': setPieceSafely(position, file, rank, PieceType.r); file++; break; case 'q': setPieceSafely(position, file, rank, PieceType.q); file++; break; case 'k': setPieceSafely(position, file, rank, PieceType.k); file++; break; default: throw new ParserError("Invalid Piece", position); } } //Active Colour if (terms[1].Length > 0) { Boolean whiteToMove; char c = (char)terms[1].ToCharArray().GetValue(0); switch (c) { case 'w': whiteToMove = true; break; case 'b': whiteToMove = false; break; default: throw new ParserError("Invalid Active Colour", position); } position.setWhiteMove(whiteToMove); } else { throw new ParserError("Invalid Active Colour", position); } //Castling Rights int castleMask = 0; if (terms.Length > 2) { for (int i = 0; i < terms[2].Length; i++) { char c = (char)terms[2].ToCharArray().GetValue(i); switch (c) { case 'K': castleMask |= (1 << Position.H1_CASTLE); break; case 'Q': castleMask |= (1 << Position.A1_CASTLE); break; case 'k': castleMask |= (1 << Position.H8_CASTLE); break; case 'q': castleMask |= (1 << Position.A8_CASTLE); break; case '-': break; default: throw new ParserError("Invalid castling flags", position); } } } position.setCastleMask(castleMask); removeInvalidCastleFlags(position); //En Passant Target Square if (terms.Length > 3) { String epString = terms[3]; if (!epString.Equals("-")) { if (epString.Length < 2) { throw new ParserError("Invalid En Passent Square", position); } position.setEpSquare(getSquare(epString)); } } try { //Halfmove Clock if (terms.Length > 4) { position.halfMoveClock = Convert.ToInt32(terms[4]); } //Full Move Counter if (terms.Length > 5) { position.fullMoveCounter = Convert.ToInt32(terms[5]); } } catch (ArgumentException ae) { //Ignore errors here since fields are optional } //Each side must have exactly one king int maxNumber = (int)PieceType.Empty + 1; int[] numPieces = new int[maxNumber]; for (int i = 0; i < maxNumber; i++) { numPieces[i] = 0; } for (file = 0; file < 8; file++) { for (rank = 0; rank < 8; rank++) { numPieces[(int)position.getPiece(Position.getSquare(file, rank))]++; } } if (numPieces[(int)PieceType.K] != 1) { throw new ParserError("Too many white kings", position); } if (numPieces[(int)PieceType.k] != 1) { throw new ParserError("Too many black kings", position); } //White must not have too many pieces int maxWPawns = 8; maxWPawns -= Math.Max(0, numPieces[(int)PieceType.N] - 2); maxWPawns -= Math.Max(0, numPieces[(int)PieceType.B] - 2); maxWPawns -= Math.Max(0, numPieces[(int)PieceType.R] - 2); maxWPawns -= Math.Max(0, numPieces[(int)PieceType.Q] - 1); if (numPieces[(int)PieceType.P] > maxWPawns) { throw new ParserError("Too many white pieces", position); } //Black must not have too many pieces int maxBPawns = 8; maxBPawns -= Math.Max(0, numPieces[(int)PieceType.n] - 2); maxBPawns -= Math.Max(0, numPieces[(int)PieceType.b] - 2); maxBPawns -= Math.Max(0, numPieces[(int)PieceType.r] - 2); maxBPawns -= Math.Max(0, numPieces[(int)PieceType.q] - 1); //Make sure king can not be captured Position pos2 = new Position(position); pos2.setWhiteMove(!position.whiteMove); if (MoveGenerator.inCheck(pos2)) { throw new ParserError("King capture possible", position); } fixupEPSquare(position); return position; }
/* * Remove EPSquare from position if it is not legal */ private static void fixupEPSquare(Position position) { int epSquare = position.getEpSquare(); if (epSquare >= 0) { ArrayList moves = MoveGenerator.mgInstance.legalMoves(position); Boolean epValid = false; foreach (Move move in moves) { if (move.destination == epSquare) { if (position.getPiece(move.origin) == (position.whiteMove ? PieceType.P : PieceType.p)) { epValid = true; break; } } } if (!epValid) { position.setEpSquare(-1); } } }
/* * Determines if two positions are equal in the sense of the draw by * the repetition rule. * Return true if positions are equal, false otherwise. */ public Boolean drawRuleEquals(Position pos) { for (int i = 0; i < 64; i++) { if (pieceLayout[i] != pos.pieceLayout[i]) return false; } if (whiteMove != pos.whiteMove) return false; if (epSquare != pos.epSquare) return false; return true; }
/* * Converts a move object into a UCI move string (long algebraic * notation), a move list can be supplied to search through. */ public static String moveObjectToString(Move move, Position position, ArrayList moves) { if ((move == null) || move.Equals(new Move(0, 0, 0))) { return "--"; } StringBuilder moveString = new StringBuilder(); int whiteKingOrigin = Position.getSquare(4, 0); int blackKingOrigin = Position.getSquare(4, 7); if ((move.origin == whiteKingOrigin) && (position.getPiece(whiteKingOrigin) == PieceType.K)) { //Check white castle if (move.destination == Position.getSquare(6, 0)) { moveString.Append("O-O"); } else if (move.destination == Position.getSquare(2, 0)) { moveString.Append("O-O-O"); } } else if ((move.origin == blackKingOrigin) && (position.getPiece(blackKingOrigin) == PieceType.k)) { //Check black castle if (move.destination == Position.getSquare(6, 7)) { moveString.Append("O-O"); } else if (move.destination == Position.getSquare(2, 7)) { moveString.Append("O-O-O"); } } if (moveString.Length == 0) { PieceType piece = position.getPiece(move.origin); moveString.Append("" + piece); int originFile = Position.getRank(move.origin); int originRank = Position.getFile(move.origin); int destinationFile = Position.getRank(move.destination); int destinationRank = Position.getFile(move.destination); //Long Algebraic Notation----- moveString.Append((char)(originFile + 'a')); moveString.Append((char)(originRank + '1')); moveString.Append(isMoveCapture(move, position) ? 'x' : '-'); //---------------------------- moveString.Append((char)(destinationFile + 'a')); moveString.Append((char)(destinationRank + '1')); if (move.promoteTo != PieceType.Empty) { moveString.Append("" + piece); } } UnMakeInfo unMake = new UnMakeInfo(); position.makeMove(move, unMake); Boolean inCheck = MoveGenerator.inCheck(position); if (inCheck) { ArrayList nextMoves = MoveGenerator.mgInstance.legalMoves(position); if (nextMoves.Count == 0) { moveString.Append('#'); } else { moveString.Append('+'); } } position.unMakeMove(move, unMake); return moveString.ToString(); }
/* * Remove castling flags that arent valid */ private static void removeInvalidCastleFlags(Position position) { int castleMask = position.getCastleMask(); int validCastle = 0; if (position.getPiece(4) == PieceType.K) { if (position.getPiece(0) == PieceType.R) validCastle |= (1 << Position.A1_CASTLE); if (position.getPiece(7) == PieceType.R) validCastle |= (1 << Position.H1_CASTLE); } if (position.getPiece(60) == PieceType.k) { if (position.getPiece(56) == PieceType.r) validCastle |= (1 << Position.A8_CASTLE); if (position.getPiece(63) == PieceType.r) validCastle |= (1 << Position.H8_CASTLE); } castleMask &= validCastle; position.setCastleMask(castleMask); }