Example #1
0
        /// <summary>
        /// コメント行を読み込み、それをノードに設定します。
        /// </summary>
        /// <remarks>
        /// コメント行は複数行に渡ることがあるため、
        /// コメント行がある間はずっとコメントを追加し続けます。
        /// </remarks>
        private void ReadCommentLines(KifMoveNode node, bool forceOneLine)
        {
            var alreadyRead = false;

            while (this.currentLine != null)
            {
                var commentData = KifUtil.ParseCommentLine(this.currentLine);
                if (commentData == null)
                {
                    if (forceOneLine && !alreadyRead)
                    {
                        ReadNextLine();
                    }

                    break;
                }

                // 必要なコメントのみ棋譜から取り出します。
                if (commentData.IsMoveComment)
                {
                    node.AddComment(commentData.Comment);
                }

                ReadNextLine();
                alreadyRead = true;
            }
        }
Example #2
0
        /// <summary>
        /// コメント行を読み込み、それをノードに設定します。
        /// </summary>
        /// <remarks>
        /// コメント行は複数行に渡ることがあるため、
        /// コメント行がある間はずっとコメントを追加し続けます。
        /// </remarks>
        private void ReadCommentLines(KifMoveNode node, bool forceOneLine)
        {
            var alreadyRead = false;

            while (this.currentLine != null)
            {
                var commentData = KifUtil.ParseCommentLine(this.currentLine);
                if (commentData == null)
                {
                    if (forceOneLine && !alreadyRead)
                    {
                        ReadNextLine();
                    }

                    break;
                }

                // 必要なコメントのみ棋譜から取り出します。
                if (commentData.IsMoveComment)
                {
                    node.AddComment(commentData.Comment);
                }

                ReadNextLine();
                alreadyRead = true;
            }
        }
Example #3
0
        /// <summary>
        /// 変化を既存のノードに追加します。
        /// </summary>
        private void MergeVariation(KifMoveNode node, KifMoveNode source)
        {
            while (node.MoveCount != source.MoveCount)
            {
                if (node.NextNode == null)
                {
                    //throw
                    return;
                }

                node = node.NextNode;
            }

            for (var next = node; next != null; next = next.VariationNode)
            {
                if (next == null)
                {
                    break;
                }

                node = next;
            }

            // 変化を追加します。
            node.VariationNode = source;
        }
Example #4
0
        /// <summary>
        /// ファイル内容から棋譜ファイルを読み込みます。
        /// </summary>
        public KifuObject Load(TextReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            this.reader      = reader;
            this.currentLine = null;
            this.lineNumber  = 0;
            this.startBoard  = null;

            // ヘッダーや局面の読み取り
            ReadNextLine();
            var head   = new KifMoveNode();
            var header = ParseHeader(head);
            var board  = this.startBoard;

            // 指し手の読み取りに入ります。
            if (this.currentLine == null)
            {
                // ファイルが終わっている場合はbod形式
                return(new KifuObject(header, board));
            }
            else if (this.isKif)
            {
                // kif形式
                return(LoadKif(header, board, head));
            }
            else
            {
                // ki2形式
                return(LoadKi2(header, board, head));
            }
        }
Example #5
0
        /// <summary>
        /// kif形式の指し手を読み込みます。
        /// </summary>
        private KifuObject LoadKif(KifuHeader header, Board board, KifMoveNode head_)
        {
            var head = ParseNodeKif(board, false);

            // KifMoveNodeからMoveNodeへ変換します。
            Exception error;
            var       root = head.ConvertToMoveNode(board, head_, out error);

            root.Regulalize();

            return(new KifuObject(header, board, root, error));
        }
Example #6
0
        /// <summary>
        /// ノードの中に含まれる'変化がある指し手番号のセット'を作成します。
        /// </summary>
        private HashSet <int> MakeVariationLineSet(KifMoveNode head)
        {
            var result = new HashSet <int>();

            for (var node = head; node != null; node = node.NextNode)
            {
                if (node.HasVariationNode)
                {
                    result.Add(node.MoveCount);
                }
            }

            return(result);
        }
Example #7
0
        /// <summary>
        /// ひとかたまりになっている一連の指し手をパースします。
        /// </summary>
        private KifMoveNode ParseMoveLinesKif(bool isVariation)
        {
            var head = new KifMoveNode();
            var last = head;

            // もし変化を読み取る場合は、開始記号を探します。
            if (isVariation)
            {
                while (this.currentLine != null)
                {
                    // 新しい変化が始まる場合は、
                    //  変化 ○手目
                    // という行から始まります。
                    var m = BeginVariationLineRegex.Match(this.currentLine);
                    if (m.Success)
                    {
                        head.MoveCount = int.Parse(m.Groups[1].Value);
                        ReadNextLine();
                        break;
                    }

                    // 複数のコメント行を読み込みます。
                    ReadCommentLines(head, true);
                }
            }

            while (this.currentLine != null)
            {
                // 指し手行を1行だけパースします。
                var node = ParseMoveLineKif(this.currentLine);
                if (node == null)
                {
                    break;
                }

                ReadNextLine();

                // 指し手の後に続く複数のコメント行を読み込みます。
                ReadCommentLines(node, false);

                // 指し手はリンクリストで保存します。
                last.NextNode = node;
                last          = node;
            }

            return(head.NextNode);
        }
Example #8
0
        /// <summary>
        /// ヘッダー部分をまとめてパースします。
        /// </summary>
        /// <remarks>
        /// 開始局面の設定も行います。
        /// </remarks>
        private KifuHeader ParseHeader(KifMoveNode head)
        {
            var header = new KifuHeader();
            var parser = new BodParser();

            while (ParseHeaderLine(this.currentLine, parser, header, head))
            {
                ReadNextLine();
            }

            if (parser.IsBoardParsing)
            {
                throw new FileFormatException(
                          "局面の読み取りを完了できませんでした。");
            }

            this.startBoard = MakeStartBoard(parser);
            return(header);
        }
Example #9
0
        /// <summary>
        /// ki2形式のファイルを読み込みます。
        /// </summary>
        private KifuObject LoadKi2(KifuHeader header, Board startBoard, KifMoveNode head_)
        {
            Exception error;
            var       cloned   = startBoard.Clone();
            var       nodeList = ParseMoveLinesKi2(cloned, out error);
            var       root     = new MoveNode
            {
                CommentList = head_.CommentList,
                PVInfoList  = head_.PVInfoList,
            };
            var last = root;

            foreach (var node in nodeList)
            {
                last.AddNextNode(node);
                last = node;
            }

            root.Regulalize();
            return(new KifuObject(header, startBoard, root, error));
        }
Example #10
0
        /// <summary>
        /// ki2形式のファイルを読み込みます。
        /// </summary>
        private KifuObject LoadKi2(KifuHeader header, Board startBoard, KifMoveNode head)
        {
            var knodeList = ParseMoveLinesKi2().ToList();
            var last      = head;

            foreach (var knode in knodeList)
            {
                last.Next = knode;
                last      = knode;
            }

            // KifNodeMoveのツリーをNodeMoveのツリーに直します。
            // 変換時にエラーが出た場合は、それまでの指し手を変換します。
            var       board = startBoard.Clone();
            Exception error = null;
            var       root  = head.Next.ConvertToMoveNode(board, head, out error);

            root.Regulalize();

            return(new KifuObject(header, startBoard, root, error));
        }
Example #11
0
        /// <summary>
        /// ひとかたまりになっている一連の指し手をパースします。
        /// </summary>
        private KifMoveNode ParseMoveLinesKif(bool isVariation)
        {
            var head = new KifMoveNode();
            var last = head;

            // もし変化を読み取る場合は、開始記号を探します。
            if (isVariation)
            {
                while (this.currentLine != null)
                {
                    // 新しい変化が始まる場合は、
                    //  変化 ○手目
                    // という行から始まります。
                    var m = BeginVariationLineRegex.Match(this.currentLine);
                    if (m.Success)
                    {
                        head.MoveCount = int.Parse(m.Groups[1].Value);
                        ReadNextLine();
                        break;
                    }

                    // 複数のコメント行を読み込みます。
                    ReadCommentLines(head, true);
                }
            }

            while (this.currentLine != null)
            {
                // 指し手行を1行だけパースします。
                var node = ParseMoveLineKif(this.currentLine);
                if (node == null)
                {
                    break;
                }

                ReadNextLine();

                // 指し手の後に続く複数のコメント行を読み込みます。
                ReadCommentLines(node, false);

                // 指し手はリンクリストで保存します。
                last.Next = node;
                last = node;
            }

            return head.Next;
        }
Example #12
0
        /// <summary>
        /// 変化を既存のノードに追加します。
        /// </summary>
        private void MergeVariation(KifMoveNode node, KifMoveNode source)
        {
            while (node.MoveCount != source.MoveCount)
            {
                if (node.Next == null)
                {
                    //throw 
                    return;
                }

                node = node.Next;
            }

            for (var next = node; next != null; next = next.Variation)
            {
                if (next == null)
                {
                    break;
                }

                node = next;
            }

            // 変化を追加します。
            node.Variation = source;
        }
Example #13
0
        /// <summary>
        /// ノードの中に含まれる'変化がある指し手番号のセット'を作成します。
        /// </summary>
        private HashSet<int> MakeVariationLineSet(KifMoveNode head)
        {
            var result = new HashSet<int>();

            for (var node = head; node != null; node = node.Next)
            {
                if (node.HasVariation)
                {
                    result.Add(node.MoveCount);
                }
            }

            return result;
        }
Example #14
0
        /// <summary>
        /// kif形式の指し手を読み込みます。
        /// </summary>
        private KifuObject LoadKif(KifuHeader header, Board board, KifMoveNode head_)
        {
            var head = ParseNodeKif(board, false);

            // KifMoveNodeからMoveNodeへ変換します。
            Exception error;
            var root = head.ConvertToMoveNode(board, head_, out error);
            root.Regulalize();

            return new KifuObject(header, board, root, error);
        }
Example #15
0
        /// <summary>
        /// ki2形式のファイルを読み込みます。
        /// </summary>
        private KifuObject LoadKi2(KifuHeader header, Board startBoard, KifMoveNode head)
        {
            var knodeList = ParseMoveLinesKi2().ToList();
            var last = head;
            foreach (var knode in knodeList)
            {
                last.Next = knode;
                last = knode;
            }

            // KifNodeMoveのツリーをNodeMoveのツリーに直します。
            // 変換時にエラーが出た場合は、それまでの指し手を変換します。
            var board = startBoard.Clone();
            Exception error = null;
            var root = head.Next.ConvertToMoveNode(board, head, out error);
            root.Regulalize();

            return new KifuObject(header, startBoard, root, error);
        }
Example #16
0
        /// <summary>
        /// ヘッダー部分をまとめてパースします。
        /// </summary>
        /// <remarks>
        /// 開始局面の設定も行います。
        /// </remarks>
        private KifuHeader ParseHeader(KifMoveNode head)
        {
            var header = new KifuHeader();
            var parser = new BodParser();

            while (ParseHeaderLine(this.currentLine, parser, header, head))
            {
                ReadNextLine();
            }

            if (parser.IsBoardParsing)
            {
                throw new FileFormatException(
                    "局面の読み取りを完了できませんでした。");
            }

            this.startBoard = MakeStartBoard(parser);
            return header;
        }
Example #17
0
        /// <summary>
        /// ファイル内容から棋譜ファイルを読み込みます。
        /// </summary>
        public KifuObject Load(TextReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            this.reader = reader;
            this.currentLine = null;
            this.lineNumber = 0;
            this.startBoard = null;

            // ヘッダーや局面の読み取り
            ReadNextLine();
            var head = new KifMoveNode();
            var header = ParseHeader(head);
            var board = this.startBoard;

            // 指し手の読み取りに入ります。
            if (this.currentLine == null)
            {
                // ファイルが終わっている場合はbod形式
                return new KifuObject(header, board);
            }
            else if (this.isKif)
            {
                // kif形式
                return LoadKif(header, board, head);
            }
            else
            {
                // ki2形式
                return LoadKi2(header, board, head);
            }
        }
Example #18
0
        /// <summary>
        /// ヘッダー行をパースします。
        /// </summary>
        private bool ParseHeaderLine(string line, BodParser parser,
                                     KifuHeader header = null, KifMoveNode head = null)
        {
            if (line == null)
            {
                // ファイルの終了を意味します。
                return false;
            }

            var commentData = KifUtil.ParseCommentLine(line);
            if (commentData != null)
            {
                // コメントはパース結果に含めます。
                if (head != null && commentData.IsMoveComment)
                {
                    head.AddComment(commentData.Comment);
                }

                return true;
            }

            // 読み飛ばすべき説明行
            if (line.Contains("手数----指手---------消費時間"))
            {
                this.isKif = true; // kif形式です。
                return true;
            }

            // 局面の読み取りを試みます。
            if (parser.TryParse(line))
            {
                return true;
            }

            var item = KifUtil.ParseHeaderItem(line);
            if (item != null)
            {
                if (item.Key == "手合割" && item.Value != "その他")
                {
                    this.startBoard = BoardTypeUtil.CreateBoardFromName(item.Value);
                }

                if (header != null)
                {
                    // 可能ならヘッダアイテムを設定します。
                    var type = KifUtil.GetHeaderType(item.Key);
                    if (type != null)
                    {
                        header[type.Value] = item.Value;
                    }
                }

                return true;
            }

            // ヘッダが正しく読めない場合、
            // 区切りなしに指し手行に入っている可能性があります。
            if (MoveLineRegex.IsMatch(line))
            {
                this.isKif = true;
            }

            return false;
        }
Example #19
0
        /// <summary>
        /// ヘッダー行をパースします。
        /// </summary>
        private bool ParseHeaderLine(string line, BodParser parser,
                                     KifuHeader header = null, KifMoveNode head = null)
        {
            if (line == null)
            {
                // ファイルの終了を意味します。
                return(false);
            }

            var commentData = KifUtil.ParseCommentLine(line);

            if (commentData != null)
            {
                // コメントはパース結果に含めます。
                if (head != null && commentData.IsMoveComment)
                {
                    head.AddComment(commentData.Comment);
                }

                return(true);
            }

            // 読み飛ばすべき説明行
            if (line.Contains("手数----指手---------消費時間"))
            {
                this.isKif = true; // kif形式です。
                return(true);
            }

            // 局面の読み取りを試みます。
            if (parser.TryParse(line))
            {
                return(true);
            }

            var item = KifUtil.ParseHeaderItem(line);

            if (item != null)
            {
                if (item.Key == "手合割" && item.Value != "その他")
                {
                    this.startBoard = BoardTypeUtil.CreateBoardFromName(item.Value);
                }

                if (header != null)
                {
                    // 可能ならヘッダアイテムを設定します。
                    var type = KifUtil.GetHeaderType(item.Key);
                    if (type != null)
                    {
                        header[type.Value] = item.Value;
                    }
                }

                return(true);
            }

            // ヘッダが正しく読めない場合、
            // 区切りなしに指し手行に入っている可能性があります。
            if (MoveLineRegex.IsMatch(line))
            {
                this.isKif = true;
            }

            return(false);
        }