/// <summary> /// Parses one single move. /// </summary> /// <param name="_board">The current board , current opening book's game board</param> /// <param name="_pgnMove">the move's PGN notation</param> /// <param name="moves">A list of all availible moves</param> /// <returns>An opening move represents the parsed response.</returns> private static OpeningMove PGNMoveParser(Board _board, string _pgnMove, List <Move> moves) { bool isCapture = _pgnMove.Contains('x'); bool test = false; if (test) { moves = MovesGenerator.GetLegalMoves(_board); } OpeningMove move = new OpeningMove(); try { //first check if it is castle if (_pgnMove.StartsWith("O-O-O")) { move.Move = moves.First(x => x.MoveType == MoveTypes.CastleQueenSide); } else if (_pgnMove.StartsWith("O-O")) { move.Move = moves.First(x => x.MoveType == MoveTypes.CastleKingSide); } else { int piece = PGNletterToPieceParser(_pgnMove[0], _board.CurrentPlayer); var pieceMoves = moves.Where(x => x.MovingPiece == piece); if (pieceMoves.Count() == 1) { move.Move = pieceMoves.ElementAt(0); } else { if (piece == Piece.BlackPawn || piece == Piece.WhitePawn) { var sourceMoves = pieceMoves.Where(x => x.SourceFile == _pgnMove[0]); if (sourceMoves.Count() == 1) { move.Move = sourceMoves.ElementAt(0); } else { if (isCapture) { string dest = _pgnMove.Substring(_pgnMove.IndexOf('x') + 1, 2); move.Move = sourceMoves.First(x => x.DestinationSquareString == dest); } else { string dest = _pgnMove.Substring(0, 2); move.Move = sourceMoves.First(x => x.DestinationSquareString.StartsWith(dest)); } } } else { IEnumerable <Move> destMoves; if (isCapture) { string dest = _pgnMove.Substring(_pgnMove.IndexOf('x') + 1, 2); destMoves = pieceMoves.Where(x => x.DestinationSquareString == dest); } else { int indexDestRank = _pgnMove.LastIndexOfAny(new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9' }); string dest = _pgnMove.Substring(indexDestRank - 1, 2); destMoves = pieceMoves.Where(x => x.DestinationSquareString == dest); } switch (destMoves.Count()) { case 1: move.Move = destMoves.ElementAt(0); break; case 2: //either rank or file ambiguity if (_pgnMove[1] >= '1' && _pgnMove[1] <= '9') { //rank ambiguity move.Move = destMoves.First(x => x.SourceRank == _pgnMove[1]); } else { move.Move = destMoves.First(x => x.SourceFile == _pgnMove[1]); } break; case 3: move.Move = destMoves.First(x => x.SourceSquareString == _pgnMove.Substring(1, 2)); break; } } } //now get move type if (_pgnMove.Contains("!!")) { move.MoveType = OpeningMoveType.Excellent; } else if (_pgnMove.Contains("!?")) { move.MoveType = OpeningMoveType.Interesting; } else if (_pgnMove.Contains("?!")) { move.MoveType = OpeningMoveType.Dubious; } else if (_pgnMove.Contains("!")) { move.MoveType = OpeningMoveType.Good; } else if (_pgnMove.Contains("??")) { move.MoveType = OpeningMoveType.Blunder; } else if (_pgnMove.Contains("?")) { move.MoveType = OpeningMoveType.Bad; } } if (move.Move == null) { throw new System.Exception("not found"); } return(move); } catch (Exception ex) { throw ex; } }
/// <summary> /// Parses the book string in the standard PGN format, and inserts it into the starting position node /// </summary> /// <param name="book">A standard PGN formatted string</param> /// <param name="startingPoint">The starting node to add responses to</param> private static void AnalyzeBook(string book, OpeningMove startingPoint) { try { string[] tags = book.Replace("\r\n", " ").Split(new string[] { "[" }, StringSplitOptions.RemoveEmptyEntries); for (int i = 6; i < tags.Length; i += 7) { string movesString = tags[i].Substring(tags[i].IndexOf(']') + 1); string[] movesArray = movesString.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); Board board = new Board(); board.StartingPosition(); //parentMove will slide, containing the parent to the move. OpeningMove parentMove = startingPoint; bool abortMatch = false; for (int j = 0; j < movesArray.Length && !abortMatch; j++) { if (j % 3 == 0) { continue; } if (parentMove.LegalMoves == null) { parentMove.LegalMoves = MovesGenerator.GetLegalMoves(board); } OpeningMove move = PGNMoveParser(board, movesArray[j], parentMove.LegalMoves); if (move.MoveType != OpeningMoveType.Excellent && move.MoveType != OpeningMoveType.Good) { abortMatch = true; break; } //to avoid duplicate entries problem, we make sure to use same instance of a move. OpeningMove storedSameMove = parentMove.Responses.FirstOrDefault(x => x.Move.EqualMove(move.Move)); if (storedSameMove == null) { move.Count = 1; parentMove.Responses.Add(move); } else { parentMove.Count++; move = storedSameMove; } parentMove = move; board.ApplyMove(move.Move); } } } catch (Exception ex) { throw ex; } }