Esempio n. 1
0
        /// <summary>
        /// ヘッダ部分を出力します。
        /// </summary>
        private void WriteHeader(TextWriter writer, KifuObject kifu)
        {
            writer.WriteLine("' ----  Ragnarok 棋譜ファイル  ----");

            // 対局者名は別腹で行きます。
            var value = kifu.Header[KifuHeaderType.BlackName];

            if (value != null)
            {
                writer.WriteLine("N+{0}", value);
            }

            value = kifu.Header[KifuHeaderType.WhiteName];
            if (value != null)
            {
                writer.WriteLine("N-{0}", value);
            }

            // 他のヘッダアイテムを書き出します。
            foreach (var item in kifu.Header)
            {
                var name = CsaUtil.GetHeaderName(item.Key);
                if (name == null)
                {
                    continue;
                }

                writer.WriteLine("${0}:{1}", name, item.Value);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// 各段のCSA局面を返します。
        /// </summary>
        private static IEnumerable <string> RankToCsa(Board board, int rank)
        {
            for (var file = Board.BoardSize; file >= 1; --file)
            {
                var piece = board[file, rank];

                yield return(CsaUtil.BoardPieceToStr(piece));
            }
        }
Esempio n. 3
0
        /// <summary>
        /// CSA形式の文字列から、局面を読み取ります。
        /// </summary>
        public static Board Parse(string csa)
        {
            if (string.IsNullOrEmpty(csa))
            {
                throw new ArgumentNullException("csa");
            }

            var parser = new CsaBoardParser();

            csa.Split(
                new char[] { '\n', '\r' },
                StringSplitOptions.RemoveEmptyEntries)
            .Where(_ => !CsaUtil.IsCommentLine(_))
            .ForEach(_ => parser.TryParse(_));

            return(parser.Board);
        }
Esempio n. 4
0
        /// <summary>
        /// 一括表現形式の局面を読み取ります。
        /// </summary>
        /// <example>
        /// P1-KY-KE-GI-KI-OU-KI-GI-KE-KY
        /// P2 * -HI *  *  *  *  * -KA *
        /// </example>
        private void ParseBoardPn(string line)
        {
            if (line[1] < '1' || '9' < line[1])
            {
                throw new ShogiException(
                          line + ": CSA形式の局面の段数が正しくありません。");
            }

            var currentRank = (int)(line[1] - '0');
            var rank        = this.parsedRank + 1;

            if (currentRank != rank)
            {
                throw new ShogiException(
                          line + ": CSA形式の局面を正しく読み込めませんでした。");
            }

            var pieceList = line.Skip(2).TakeBy(3)
                            .Select(_ => new string(_.ToArray()))
                            .Select(_ => CsaUtil.StrToBoardPiece(_))
                            .Where(_ => _ != null)
                            .ToList();

            if (pieceList.Count() != Board.BoardSize ||
                pieceList.Any(_ => _ == null))
            {
                throw new ShogiException(
                          line + ": CSA形式の局面を正しく読み込めませんでした。");
            }

            // 局面は駒を全くおかない状態で初期化します。
            if (this.board == null)
            {
                this.board = new Board(false);
            }

            pieceList.ForEachWithIndex((piece, index) =>
            {
                var isNone = (piece.PieceType == PieceType.None);
                var file   = Board.BoardSize - index;

                this.board[file, rank] = (isNone ? null : piece);
            });

            this.parsedRank += 1;
        }
Esempio n. 5
0
        /// <summary>
        /// 棋戦情報などをパースします。
        /// </summary>
        private void ParseHeader(string line)
        {
            var item = CsaUtil.ParseHeaderItem(line);

            if (item == null)
            {
                throw new FileFormatException(
                          this.lineNumber,
                          line + ": CSA形式のヘッダ行が正しくありません。");
            }

            var type = CsaUtil.GetHeaderType(item.Key);

            if (type != null)
            {
                this.header[type.Value] = item.Value;
            }
        }
Esempio n. 6
0
        /// <summary>
        /// 落とす駒をパースします。
        /// </summary>
        /// <remarks>
        /// 00OU など4文字形式の駒をパースします。
        /// </remarks>
        private PieceSquare ParsePiece(string str)
        {
            var file     = (int)(str[0] - '0');
            var rank     = (int)(str[1] - '0');
            var pieceStr = str.Substring(2);
            var piece    = CsaUtil.StrToPiece(pieceStr);

            if (piece == null)
            {
                throw new ShogiException(
                          str + ": CSA形式の駒を正しく読み込めませんでした。");
            }

            return(new PieceSquare
            {
                Square = new Square(file, rank),
                Piece = piece,
            });
        }
Esempio n. 7
0
        /// <summary>
        /// 持ち駒をCSA形式に変換します。
        /// </summary>
        /// <example>
        /// P+00KIOOFU
        /// </example>
        private static string HandToCsa(Board board, BWType turn)
        {
            var handList =
                from pieceType in EnumEx.GetValues <PieceType>()
                let count                     = board.GetCapturedPieceCount(pieceType, turn)
                                      let str = string.Format("00{0}",
                                                              CsaUtil.PieceToStr(new Piece(pieceType)))
                                                let list = Enumerable.Range(1, count).Select(_ => str)
                                                           select string.Join("", list.ToArray());

            // ToArray()しないと、MONOでstring.Joinのコンパイルに失敗します。
            var array = handList.ToArray();

            if (!array.Any())
            {
                return(string.Empty);
            }
            else
            {
                return(string.Format("P{0}{1}",
                                     turn == BWType.Black ? "+" : "-",
                                     string.Join("", array)));
            }
        }
Esempio n. 8
0
        /// <summary>
        /// <paramref name="move"/>をCSA形式に変換します。
        /// </summary>
        public static string ToCsa(this Move move)
        {
            if (move == null)
            {
                throw new ArgumentNullException("move");
            }

            if (!move.Validate())
            {
                throw new ArgumentException("move");
            }

            if (move.IsSpecialMove)
            {
                return(move.SpecialMoveType.ToCsa());
            }

            var sb = new StringBuilder();

            sb.Append(
                move.BWType == BWType.Black ? "+" :
                move.BWType == BWType.White ? "-" :
                "");

            if (move.SrcSquare != null)
            {
                sb.Append(move.SrcSquare.File);
                sb.Append(move.SrcSquare.Rank);
            }
            else
            {
                // 駒打の場合
                sb.Append("00");
            }

            if (move.DstSquare != null)
            {
                sb.Append(move.DstSquare.File);
                sb.Append(move.DstSquare.Rank);
            }
            else
            {
                // ほんとはエラー
                sb.Append("00");
            }

            var piece = (
                move.ActionType == ActionType.Drop ?
                new Piece(move.DropPieceType) :
                move.MovePiece);

            if (move.IsPromote)
            {
                // 駒を成った場合は、なった後の駒を出力します。
                piece = new Piece(piece.PieceType, true);
            }

            sb.Append(CsaUtil.PieceToStr(piece));

            return(sb.ToString());
        }
Esempio n. 9
0
        /// <summary>
        /// CSA形式の指し手を解析します。
        /// </summary>
        public static Move CsaToMove(this Board board, string csa)
        {
            if (board == null)
            {
                throw new ArgumentNullException("board");
            }

            if (string.IsNullOrEmpty(csa))
            {
                throw new ArgumentNullException("csa");
            }

            // 特殊な指し手
            var smove = board.CsaToSpecialMove(csa);

            if (smove != null)
            {
                return(smove);
            }

            // 普通の指し手
            var m = MoveRegex.Match(csa);

            if (!m.Success)
            {
                return(null);
            }

            var c    = m.Groups[1].Value;
            var side = (
                c == "+" ? BWType.Black :
                c == "-" ? BWType.White :
                BWType.None);

            // 移動前の位置
            var srcFile   = int.Parse(m.Groups[2].Value);
            var srcRank   = int.Parse(m.Groups[3].Value);
            var srcSquare =
                (srcFile == 0 || srcRank == 0
                ? (Square)null
                : new Square(srcFile, srcRank));

            // 移動後の位置
            var dstFile   = int.Parse(m.Groups[4].Value);
            var dstRank   = int.Parse(m.Groups[5].Value);
            var dstSquare =
                (dstFile == 0 || dstRank == 0
                ? (Square)null
                : new Square(dstFile, dstRank));

            // 駒
            var piece = CsaUtil.StrToPiece(m.Groups[6].Value);

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

            if (srcSquare == null)
            {
                // 駒打ちの場合
                return(Move.CreateDrop(side, dstSquare, piece.PieceType));
            }
            else
            {
                // 駒の移動の場合、成りの判定を行います。
                var srcPiece = board[srcSquare];
                if (srcPiece == null || !srcPiece.Validate())
                {
                    return(null);
                }

                // CSA形式の場合、駒が成ると駒の種類が変わります。
                var isPromote = (!srcPiece.IsPromoted && piece.IsPromoted);
                if (isPromote)
                {
                    piece = new Piece(piece.PieceType, false);
                }

                return(Move.CreateMove(side, srcSquare, dstSquare, piece, isPromote));
            }
        }
Esempio n. 10
0
        /// <summary>
        /// ヘッダー行をパースします。
        /// </summary>
        private bool ParseLine(string line, CsaBoardParser parser)
        {
            if (line == null)
            {
                // ファイルの終了を意味します。
                return(false);
            }

            if (CsaUtil.IsCommentLine(line))
            {
                return(true);
            }

            // 局面の読み取りを試みます。
            if (parser.TryParse(line))
            {
                if (parser.HasBoard && !parser.IsBoardParsing)
                {
                    this.startBoard = parser.Board.Clone();
                    this.board      = this.startBoard.Clone();
                }

                return(true);
            }

            switch (line[0])
            {
            case 'V':
                return(true);

            case 'N':
                ParseName(line);
                return(true);

            case '$':
                ParseHeader(line);
                return(true);

            case '+':
            case '-':
            case '%':
                var move = ParseMove(line);
                var node = new MoveNode
                {
                    Move = move,
                };

                this.lastNode.AddNextNode(node);
                this.lastNode = node;
                return(true);

            case 'T':
                var seconds = ParseTime(line);
                if (this.lastNode != null)
                {
                    this.lastNode.DurationSeconds = seconds;
                }
                return(true);
            }

            return(false);
        }