Ejemplo n.º 1
0
        /// <summary>
        /// Ki2形式の複数の指し手をパースします。
        /// </summary>
        private IEnumerable <KifMoveNode> ParseMoveLinesKi2()
        {
            while (this.currentLine != null)
            {
                var smove = KifUtil.ParseSpecialMove(this.currentLine);
                if (smove != null)
                {
                    yield return(new KifMoveNode
                    {
                        Move = smove,
                    });
                }

                var c = this.currentLine[0];
                if (c != '▲' && c != '△' && c != '▼' && c != '▽')
                {
                    ReadNextLine();
                    continue;
                }

                var list = ParseMoveLineKi2(this.currentLine);
                foreach (var move in list)
                {
                    yield return(new KifMoveNode
                    {
                        Move = move,
                    });
                }

                ReadNextLine();
            }
        }
Ejemplo n.º 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;
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// コメント行かどうか調べます。
        /// </summary>
        private bool IsCommentLine(string line)
        {
            if (line == null)
            {
                throw new ArgumentNullException("line");
            }

            return(KifUtil.IsCommentLine(line));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// ヘッダ部分を出力します。
        /// </summary>
        private void WriteHeader(TextWriter writer, KifuObject kifu)
        {
            writer.WriteLine("# ----  棋譜ファイル  ----");

            foreach (var item in kifu.Header)
            {
                var name = KifUtil.GetHeaderName(item.Key);
                if (name == null)
                {
                    continue;
                }

                writer.WriteLine("{0}:{1}", name, item.Value);
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// 局面の各段をbod形式に直します。
        /// </summary>
        private static string RankToBod(Board board, int rank)
        {
            var sb = new StringBuilder();

            sb.Append("|");

            // 9筋が一番左で、1筋は右になります。
            for (var file = Board.BoardSize; file >= 1; --file)
            {
                sb.Append(KifUtil.PieceToStr(board[file, rank]));
            }

            sb.Append("|");
            sb.Append(IntConverter.Convert(NumberType.Kanji, rank));

            return(sb.ToString());
        }
Ejemplo n.º 6
0
        /// <summary>
        /// bod形式の文字列から、局面を読み取ります。
        /// </summary>
        public static Board Parse(string text)
        {
            if (text == null)
            {
                throw new ArgumentNullException("text");
            }

            var parser = new BodParser();
            var lines  = text.Split(
                new char[] { '\n', '\r' },
                StringSplitOptions.RemoveEmptyEntries);

            foreach (var line in lines)
            {
                if (KifUtil.IsCommentLine(line))
                {
                    continue;
                }

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

                var item = KifUtil.ParseHeaderItem(line);
                if (item != null)
                {
                    continue;
                }

                break;
            }

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

            return(parser.Board);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// 持ち駒を文字列に直します。
        /// </summary>
        private static string HandToBod(Board board, BWType turn)
        {
            var list =
                from pieceType in EnumEx.GetValues <PieceType>()
                let obj = new
            {
                Piece = new Piece(pieceType, false),
                Count = board.GetHand(pieceType, turn),
            }
            where obj.Count > 0
            select string.Format("{0}{1}{2} ",
                                 KifUtil.PieceToChar(obj.Piece),
                                 (obj.Count >= 10 ? "十" : ""),
                                 (obj.Count == 10 || obj.Count == 1 ? "" :
                                  IntConverter.Convert(NumberType.Kanji, obj.Count % 10)));

            var array = list.ToArray();

            return(array.Any() ? string.Join("", array) : "なし");
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Ki2形式の複数の指し手をパースします。
        /// </summary>
        private IEnumerable <MoveNode> ParseMoveLinesKi2(Board board, out Exception error)
        {
            var nodes = new List <MoveNode>();

            error = null;
            while (this.currentLine != null && error == null)
            {
                var smove = KifUtil.ParseSpecialMove(this.currentLine);
                if (smove != null)
                {
                    nodes.Add(new MoveNode
                    {
                        Move = Move.CreateSpecialMove(
                            smove.BWType,
                            smove.SpecialMoveType)
                    });
                }

                var c = this.currentLine[0];
                if (c != '▲' && c != '△' && c != '▼' && c != '▽')
                {
                    ReadNextLine();
                    continue;
                }

                var list = ParseMoveLineKi2(board, this.currentLine, ref error);
                foreach (var move in list)
                {
                    nodes.Add(new MoveNode
                    {
                        Move = move,
                    });
                }

                ReadNextLine();
            }

            return(nodes);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// bod形式の各駒を読み取ります。
        /// </summary>
        private BoardPiece ParsePiece(int file, int rank, string line)
        {
            var index    = (Board.BoardSize - file) * 2 + 1;
            var pieceStr = line.Substring(index, 2);

            var piece = KifUtil.StrToPiece(pieceStr);

            if (piece == null)
            {
                throw new ShogiException(
                          string.Format(
                              "局面の{0}段目の駒'{1}'が正しくありません。",
                              rank, pieceStr));
            }

            if (piece.PieceType == PieceType.None)
            {
                return(null);
            }

            return(piece);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// 持ち駒の各駒をパースします。
        /// </summary>
        /// <remarks>
        /// 各駒文字を最初の漢字で表し、後に続く漢数字でその数を示します。
        /// </remarks>
        private Tuple <PieceType, int> ParseHandPiece(BWType bwType,
                                                      string handPieceText)
        {
            // 駒の種類を取得します。
            var piece = KifUtil.CharToPiece(handPieceText[0]);

            if (piece == null)
            {
                throw new ShogiException(
                          string.Format(
                              "{0}手の持ち駒'{1}'が正しくありません。",
                              bwType == BWType.Black ? "先" : "後",
                              handPieceText));
            }

            if (piece.IsPromoted)
            {
                throw new ShogiException(
                          string.Format(
                              "{0}手の持ち駒に成り駒があります。",
                              bwType == BWType.Black ? "先" : "後"));
            }

            // 駒の数指定があれば、それを解析します。
            int count = 1;

            if (handPieceText.Length > 1)
            {
                var numText    = handPieceText.Substring(1);
                var normalized = StringNormalizer.NormalizeNumber(numText, true);

                count = int.Parse(normalized);
            }

            return(Tuple.Create(piece.PieceType, count));
        }
Ejemplo n.º 11
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);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// 局面を示す各行の読み込みを試行します。
        /// </summary>
        public bool TryParse(string line)
        {
            if (string.IsNullOrEmpty(line))
            {
                throw new ArgumentNullException("line");
            }

            if (IsBoardParsing)
            {
                ParseBoardLine(line);
                return(true);
            }

            // 局面の解析
            if (line.Contains("9 8 7 6 5 4 3 2 1"))
            {
                this.state = 1;
                return(true);
            }

            // 手数
            if (Regex.IsMatch(line, @"^\s*手数="))
            {
                // 手数は無視します。
                return(true);
            }

            // 手番
            if (Regex.IsMatch(line, @"^\s*(下手|先手)番"))
            {
                SetTurn(BWType.Black);
                return(true);
            }

            if (Regex.IsMatch(line, @"^\s*(上手|後手)番"))
            {
                SetTurn(BWType.White);
                return(true);
            }

            // ヘッダの解析
            var item = KifUtil.ParseHeaderItem(line);

            if (item != null)
            {
                if (item.Key.Contains("上手") || item.Key.Contains("下手"))
                {
                    SetHandicapTurn();
                }

                // 持駒の解析
                if (item.Key == "先手の持駒" || item.Key == "下手の持駒")
                {
                    ParseHand(BWType.Black, item.Value);
                    return(true);
                }

                if (item.Key == "後手の持駒" || item.Key == "上手の持駒")
                {
                    ParseHand(BWType.White, item.Value);
                    return(true);
                }
            }

            return(false);
        }