/// <summary> /// Parse a metadata draw from the given PGN content. /// </summary> /// <param name="game">The chess game with all previous draws.</param> /// <param name="content">The PGN content to be parsed.</param> /// <returns>The parsed metadata draw</returns> private ChessDraw?parseMetadataDraw(ChessGame game, string content) { ChessDraw?draw = null; string original = content; try { // remove not significant markups ('x', '+', '#', '=') content = content.Replace("x", ""); content = content.Replace("+", ""); content = content.Replace("#", ""); content = content.Replace("=", ""); // parse drawing piece type ChessPieceType type = (char.IsUpper(content[0])) ? parseType(content[0]) : ChessPieceType.Peasant; content = char.IsUpper(content[0]) ? content.Substring(1, content.Length - 1) : content; // parse promotion piece type ChessPieceType?promotionType = (char.IsUpper(content[content.Length - 1])) ? (ChessPieceType?)parseType(content[content.Length - 1]) : null; content = char.IsUpper(content[content.Length - 1]) ? content.Substring(0, content.Length - 1) : content; // parse row / column hints int hintRow; hintRow = (content.Length == 3 && int.TryParse(content.Substring(0, 1), out hintRow)) ? (hintRow - 1) : -1; int hintColumn = (content.Length == 3 && content[0] >= 'a' && content[0] <= 'h') ? (content[0] - 'a') : -1; content = (content.Length == 3) ? content.Substring(1, content.Length - 1) : content; // make sure that the content has only 2 characters left if (content.Length > 2 || !ChessPosition.AreCoordsValid(content)) { return(null); } // determine the old and new position of the drawing chess piece var newPos = new ChessPosition(content); // compute all possible allied draws var alliedDraws = game.GetDraws(true); // find the draw instance in the list of all possible draws draw = alliedDraws .Where(x => x.DrawingPieceType == type && x.NewPosition == newPos && x.PeasantPromotionPieceType == promotionType && (hintRow == -1 || x.OldPosition.Row == hintRow) && (hintColumn == -1 || x.OldPosition.Column == hintColumn) ).First(); // TODO: implement parser logic for en-passant } catch (Exception) { Console.WriteLine($"unable to parse \"{ original }\"\n{ game.Board.ToString() }\n"); } return(draw); }
private void testPeasantPromotion() { // simulate for white and black side for (int colorValue = 0; colorValue < 2; colorValue++) { var allyColor = (ChessColor)colorValue; var enemyColor = allyColor.Opponent(); // go through all columns where the promoting peasant is moving foreward for (int fwCol = 0; fwCol < 8; fwCol++) { int fwRow = (allyColor == ChessColor.White) ? 6 : 1; var fwPos = new ChessPosition(fwRow, fwCol); var pieces = new List <ChessPieceAtPos>() { new ChessPieceAtPos(new ChessPosition(4, 0), new ChessPiece(ChessPieceType.King, ChessColor.White, true)), new ChessPieceAtPos(new ChessPosition(4, 7), new ChessPiece(ChessPieceType.King, ChessColor.Black, true)), new ChessPieceAtPos(fwPos, new ChessPiece(ChessPieceType.Peasant, allyColor, true)), }; int catchRow = (allyColor == ChessColor.White) ? 7 : 0; int leftCatchCol = fwCol - 1; int rightCatchCol = fwCol + 1; var enemyPeasant = new ChessPiece(ChessPieceType.Peasant, enemyColor, true); ChessPosition posCatchLeft; ChessPosition posCatchRight; if (ChessPosition.AreCoordsValid(catchRow, leftCatchCol)) { posCatchLeft = new ChessPosition(catchRow, leftCatchCol); pieces.Add(new ChessPieceAtPos(posCatchLeft, enemyPeasant)); } if (ChessPosition.AreCoordsValid(catchRow, rightCatchCol)) { posCatchRight = new ChessPosition(catchRow, rightCatchCol); pieces.Add(new ChessPieceAtPos(posCatchRight, enemyPeasant)); } IChessBoard board = new ChessBoard(pieces); var draws = ChessDrawGenerator.Instance.GetDraws(board, fwPos, null, true); Assert.True(draws.Count() == (4 * ((fwCol % 7 == 0) ? 2 : 3))); foreach (var draw in draws) { board = new ChessBoard(pieces); board = board.ApplyDraw(draw); Assert.True(board.AllPieces.All(x => x.Piece.Color == enemyColor || x.Piece.Type != ChessPieceType.Peasant)); } } } }
/// <summary> /// Make a human user put the next draw via CLI. /// </summary> /// <param name="board">The chess board representing the current game situation.</param> /// <param name="previousDraw">The preceding draw made by the enemy.</param> /// <returns>the next chess draw</returns> public ChessDraw GetNextDraw(IChessBoard board, ChessDraw?previousDraw) { ChessPosition oldPosition; ChessPosition newPosition; ChessPieceType?promotionPieceType = null; do { // get draw from user input Console.Write("Please make your next draw (e.g. 'e2-e4): "); string userInput = Console.ReadLine().Trim().ToLower(); // parse user input if (userInput.Length == 5) { // parse coord strings string oldPosString = userInput.Substring(0, 2); string newPosString = userInput.Substring(3, 2); // validate coord strings if (ChessPosition.AreCoordsValid(oldPosString) && ChessPosition.AreCoordsValid(newPosString)) { // init chess positions oldPosition = new ChessPosition(oldPosString); newPosition = new ChessPosition(newPosString); // make sure that the player possesses the the chess piece he is moving (simple validation) if (board.IsCapturedAt(oldPosition) && board.GetPieceAt(oldPosition).Color == Side) { break; } else { Console.Write("There is no chess piece to be moved onto the field you put! "); } } } else { Console.Write("Your input needs to be of the syntax in the example! "); } }while (true); // handle peasant promotion if (board.IsCapturedAt(oldPosition) && board.GetPieceAt(oldPosition).Type == ChessPieceType.Peasant && (Side == ChessColor.White && newPosition.Row == 7) || (Side == ChessColor.Black && newPosition.Row == 0)) { do { // get draw from user input Console.Write("You have put a promotion draw. Please choose the type you want to promote to (options: Bishop=B, Knight=N, Rook=R, Queen=Q): "); string userInput = Console.ReadLine().Trim().ToLower().ToLower(); if (userInput.Length == 1) { switch (userInput[0]) { case 'b': promotionPieceType = ChessPieceType.Bishop; break; case 'n': promotionPieceType = ChessPieceType.Knight; break; case 'r': promotionPieceType = ChessPieceType.Rook; break; case 'q': promotionPieceType = ChessPieceType.Queen; break; } if (promotionPieceType == null) { Console.Write("Your input needs to be a letter like in the example! "); } } }while (promotionPieceType == null); } return(new ChessDraw(board, oldPosition, newPosition, promotionPieceType)); }