Ejemplo n.º 1
0
        /// <summary>
        /// 別のKifuTreeをマージする。
        ///
        /// マージされた棋譜の本譜の末尾の局面を指していて欲しい気もするが…。
        /// せめて、マージされた開始局面を指すようにするか。
        ///
        /// エラーがあればその内容を文字列として返す。
        /// </summary>
        /// <param name="tree"></param>
        public string Merge(KifuTree tree)
        {
            // このsfenの局面にマージする。
            var sfen = tree.rootSfen;

            // このnodeを探す
            var node = SearchNode(sfen);

            if (node == null)
            {
                return("メイン棋譜にマージするための開始局面がありませんでした。");
            }

            // このnodeにマージしていく。
            tree.RewindToRoot();

            MergeSub(tree);

            return(null);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 棋譜ファイルを読み込む。
        /// this.Treeに反映する。また本譜の手順の最終局面までthis.Tree.posを自動的に進める。
        /// フォーマットは自動判別。
        /// CSA/KIF/KI2/PSN/SFEN形式を読み込める。
        ///
        /// ファイル丸ごと読み込んでstring型に入れて引数に渡すこと。
        /// 読み込めたところまでの棋譜を反映させる。読み込めなかった部分やエラーなどは無視する。
        ///
        /// エラーがあった場合は、そのエラーの文字列が返る。
        /// エラーがなければnullが返る。
        /// </summary>
        /// <param name="filename"></param>
        public string FromString(string content /* , KifuFileType kf */)
        {
            // なるべくファジーに判定する

            /// <summary>
            /// 文字列がsfenっぽいならtrue
            /// (position ){,1}((sfen ){,1}(.*\/){8})|(startpos)
            /// 大文字小文字の差異も許容しておく
            /// </summary>
            bool isSfen(string line)
            {
                string[] token = line.Split(' ');
                if (token.Length <= 3)
                {
                    return(false);
                }
                int i = 0;

                if (token[i].ToLower() == "position")
                {
                    ++i;
                }                                              // 先頭のpositionは任意
                if (token[i].ToLower() == "startpos")
                {
                    return(true);
                }                                                      // 平手の開始局面を表すsfenだった
                if (token[i].ToLower() == "sfen")
                {
                    ++i;
                }                                          // sfenも必須ではないようにする
                if (CountKeywrod(token[i], '/') == 8)
                {
                    return(true);
                }                                                      // 最初のトークンで/が8個ならおそらくsfenだろう
                return(false);
            }

            var e = Tree.PropertyChangedEventEnable;

            try
            {
                // イベントの一時抑制
                Tree.PropertyChangedEventEnable = false;

                Init();

                // 棋譜リストの更新をしないモードだと初期化されないので棋譜リストを明示的に初期化する。
                if (!EnableKifuList)
                {
                    Tree.ResetKifuList();
                }

                var lines = content.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);

                if (lines.Length == 0)
                {
                    return("棋譜が空でした。");
                }

                var line = lines[0];

                // sfen形式なのか?
                if (isSfen(line))
                {
                    return(FromSfenString(line));
                }

                // PSN形式なのか?
                if (line.StartsWith("[Sente"))
                {
                    return(FromPsnString(lines, KifuFileType.PSN));
                }

                // PSN2形式なのか?
                if (line.StartsWith("[Black"))
                {
                    return(FromPsnString(lines, KifuFileType.PSN2));
                }

                // CSA形式なのか?
                if (line.StartsWith("V2") || line.StartsWith("N+") || line.StartsWith("'") || line.StartsWith("+") || line.StartsWith("-")) // 将棋所だと"V2.2"など書いてあるはず。バージョンなしでも許容する。
                {
                    return(FromCsaString(lines, KifuFileType.CSA));
                }

                // JSON形式なのか?
                if (line.StartsWith("{"))
                {
                    return(FromJsonString(content, KifuFileType.JSON));
                }

                // KIF/KI2形式なのか?
                if (line.StartsWith("#") || line.IndexOf(":") > 0 || line.StartsWith("先手") || line.StartsWith("後手") || line.IndexOf("▲") > 0 || line.IndexOf("△") > 0)
                {
                    return(FromKifString(lines, KifuFileType.KIF));
                }

                return("棋譜の形式が判別できませんでした。");
            }
            finally
            {
                // -- 本譜の手順の末尾に移動。

                Tree.RewindToRoot();

                GotoLastMove();

                // イベントの一時抑制を解除して、更新通知を送る。
                Tree.PropertyChangedEventEnable = e;
                Tree.RaisePropertyChanged("KifuList", new List <KifuListRow>(Tree.KifuList));
                Tree.RaisePropertyChanged("Position", Tree.position.Clone());
            }
        }