Exemplo n.º 1
0
        /// <summary>
        /// Create a <see cref="PgnGame" /> from a tokenized game hot off being parsed.
        /// </summary>
        /// <param name="pgnText">The original pgn text.</param>
        /// <param name="tokenizedPgnGame">The just-parsed tokenized game.</param>
        /// <param name="pgnConfiguration">The configuration to use for the game.</param>
        /// <returns>The assembled PgnGame object.</returns>
        internal static PgnGame AssembleGameFromTokens(
            string pgnText,
            Game.TokenizedPgnGame tokenizedPgnGame,
            PgnConfiguration pgnConfiguration)
        {
            var tagDictionary = tokenizedPgnGame.Tags
                                .Select(t => new GameTag()
            {
                Name  = t.Item1,
                Value = t.Item2,
            })
                                .GroupBy(tag => tag.Name)
                                .ToDictionary(
                grp => grp.Key,
                grp => new GameTag()
            {
                Name  = grp.First().Name,
                Value = grp.First().Value,
            });

            (GamePly firstPly, GameResult _) = ParsePlies(tokenizedPgnGame.Tokens, pgnConfiguration);
            return(new PgnGame()
            {
                AllTags = tagDictionary,
                FirstPly = firstPly,
                OriginalPgnText = pgnText,
            });
        }
Exemplo n.º 2
0
        private static void ApplyTokensToPly(
            GamePly ply,
            List <Tokens.Token> metaTokens,
            PgnConfiguration pgnConfiguration)
        {
            foreach (var mt in metaTokens)
            {
                if (mt.TryAsComment(out var comment))
                {
                    var annotations = comment.Parts
                                      .Where(p => p.IsAnnotation)
                                      .Select(p =>
                    {
                        if (p.TryAsAnnotation(out var annotation))
                        {
                            return(annotation);
                        }

                        return(null);
                    })
                                      .ToList();
                    foreach (var annotation in annotations)
                    {
                        ply.Annotations.Add(new Annotation()
                        {
                            Text = annotation.Text,
                        });
                    }
                }
                else if (mt.TryAsLine(out var line))
                {
                    (GamePly linePly, _) = ParsePlies(line.Line, pgnConfiguration);
                    ply.AlternateNextMoves.Add(linePly);
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Parses a tokenized line.
        /// </summary>
        /// <param name="lineTokens">A collection of tokens from the body of a game, or
        /// from a recursive line.</param>
        /// <param name="pgnConfiguration">The configuration to use for the game.</param>
        /// <returns>The root game ply and the final result token.</returns>
        /// <exception cref="PgnFormatException">Thrown if the content of a result token contained invalid data.</exception>
        internal static (GamePly, GameResult) ParsePlies(
            IEnumerable <Tokens.Token> lineTokens,
            PgnConfiguration pgnConfiguration)
        {
            GameResult resultFromToken = GameResult.Ongoing;
            GamePly    currentPly      = new GamePly();
            GamePly    resultPly       = currentPly;
            var        tokenBuffer     = new List <Tokens.Token>();

            foreach (var t in lineTokens)
            {
                if (t.TryAsPly(out var ply))
                {
                    currentPly.San = ply.San;

                    if (currentPly.PreviousPly != null)
                    {
                        ApplyTokensToPly(
                            currentPly.PreviousPly,
                            tokenBuffer,
                            pgnConfiguration);
                    }

                    tokenBuffer.Clear();
                    currentPly.NextPlyInMainLine = new GamePly();
                    var previousPly = currentPly;
                    currentPly             = currentPly.NextPlyInMainLine;
                    currentPly.PreviousPly = previousPly;
                    resultPly = previousPly;
                }
                else if (t.TryAsNull(out var nullMove))
                {
                    currentPly.San = nullMove.NullMoveText;
                    if (pgnConfiguration.RewriteSan)
                    {
                        currentPly.San = RewriteSan(currentPly.San, pgnConfiguration);
                    }

                    currentPly.SanIsNullMove = true;
                    if (currentPly.PreviousPly != null)
                    {
                        ApplyTokensToPly(
                            currentPly.PreviousPly,
                            tokenBuffer,
                            pgnConfiguration);
                    }

                    tokenBuffer.Clear();
                    currentPly.NextPlyInMainLine = new GamePly();
                    var previousPly = currentPly;
                    currentPly             = currentPly.NextPlyInMainLine;
                    currentPly.PreviousPly = previousPly;
                    resultPly = previousPly;
                }
                else if (t.IsComment || t.IsLine || t.IsNag)
                {
                    tokenBuffer.Add(t);
                }
                else if (t.TryAsResult(out var resultToken))
                {
                    if (resultToken.IsWhiteWins)
                    {
                        resultFromToken = GameResult.WhiteWins;
                    }
                    else if (resultToken.IsBlackWins)
                    {
                        resultFromToken = GameResult.BlackWins;
                    }
                    else if (resultToken.IsDraw)
                    {
                        resultFromToken = GameResult.Draw;
                    }
                    else if (resultToken.IsUnspecified)
                    {
                        resultFromToken = GameResult.Ongoing;
                    }
                    else
                    {
                        throw new PgnFormatException($"An unknown result was encountered: '{resultToken}'");
                    }
                }
                else if (t.IsMoveNumber || t.IsBlackMoveNumber)
                {
                    // We don't really care about these
                }
                else
                {
                    throw new PgnFormatException("Unknown token or known tag in incorect context.");
                }
            }

            if (currentPly.PreviousPly == null)
            {
                return(null, resultFromToken);
            }

            GamePly firstPly = resultPly;

            if (resultPly.NextPlyInMainLine?.San == null)
            {
                resultPly.NextPlyInMainLine = null;
            }

            while (firstPly.PreviousPly != null)
            {
                firstPly = firstPly.PreviousPly;
            }

            return(firstPly, resultFromToken);
        }
Exemplo n.º 4
0
        private static string RewriteSan(string san, PgnConfiguration pgnConfiguration)
        {
            string rewritten = san;

            foreach (var inputCharset in pgnConfiguration.InputCharsets)
            {
                (var pawnSan, var pawn) = ReplaceAny(
                    san,
                    inputCharset.PawnChars.ToArray(),
                    pgnConfiguration.OutputCharsets.PawnChars.First());
                if (pawn)
                {
                    return(pawnSan);
                }

                (var bishopSan, var bishop) = ReplaceAny(
                    san,
                    inputCharset.BishopChars.ToArray(),
                    pgnConfiguration.OutputCharsets.BishopChars.First());
                if (bishop)
                {
                    return(bishopSan);
                }

                (var knightSan, var knight) = ReplaceAny(
                    san,
                    inputCharset.KnightChars.ToArray(),
                    pgnConfiguration.OutputCharsets.RookChars.First());
                if (knight)
                {
                    return(knightSan);
                }

                (var rookSan, var rook) = ReplaceAny(
                    san,
                    inputCharset.RookChars.ToArray(),
                    pgnConfiguration.OutputCharsets.RookChars.First());
                if (rook)
                {
                    return(rookSan);
                }

                (var queenSan, var queen) = ReplaceAny(
                    san,
                    inputCharset.QueenChars.ToArray(),
                    pgnConfiguration.OutputCharsets.QueenChars.First());
                if (queen)
                {
                    return(queenSan);
                }

                (var kingSan, var king) = ReplaceAny(
                    san,
                    inputCharset.KingChars.ToArray(),
                    pgnConfiguration.OutputCharsets.KingChars.First());
                if (king)
                {
                    return(kingSan);
                }
            }

            return(rewritten);
        }