Пример #1
0
        /// <summary>
        /// 各段の駒文字を返します。
        /// </summary>
        private static IEnumerable <string> RankToSfen(Board board, int rank)
        {
            var spaceCount = 0;

            for (var file = Board.BoardSize; file >= 1; --file)
            {
                var piece = board[file, rank];

                if (piece == null)
                {
                    // 駒がない場合
                    spaceCount += 1;
                }
                else
                {
                    // 駒がある場合
                    if (spaceCount > 0)
                    {
                        yield return(spaceCount.ToString());

                        spaceCount = 0;
                    }

                    yield return(SfenUtil.PieceToSfen(piece));
                }
            }

            // 空白の数は数字で示します。
            if (spaceCount > 0)
            {
                yield return(spaceCount.ToString());
            }
        }
Пример #2
0
        /// <summary>
        /// 持ち駒を読み込みます。
        /// </summary>
        private static void ParseHand(Board board, string sfen)
        {
            if (sfen[0] == '-')
            {
                // 何もする必要がありません。
                return;
            }

            var count = 0;

            foreach (var c in sfen)
            {
                if ('0' <= c && c <= '9')
                {
                    // 10と数字が並ぶ可能性があります。
                    count = count * 10 + (c - '0');
                }
                else
                {
                    var piece = SfenUtil.SfenToPiece(c);
                    if (piece == null)
                    {
                        throw new SfenException(
                                  "SFEN形式の持ち駒'" + c + "'が正しくありません。");
                    }

                    // 持ち駒の数は0以上に合わせます。
                    var pcount = Math.Max(count, 1);
                    board.SetHand(piece.PieceType, piece.BWType, pcount);
                    count = 0;
                }
            }
        }
Пример #3
0
        /// <summary>
        /// 持ち駒を読み込みます。
        /// </summary>
        private static void ParseHand(Board board, string sfen)
        {
            if (sfen[0] == '-')
            {
                // 何もする必要がありません。
                return;
            }

            var count = 1;

            foreach (var c in sfen)
            {
                if ('1' <= c && c <= '9')
                {
                    count = c - '0';
                }
                else
                {
                    var piece = SfenUtil.SfenToPiece(c);
                    if (piece == null)
                    {
                        throw new SfenException(
                                  "SFEN形式の持ち駒'" + c + "'が正しくありません。");
                    }

                    board.SetHand(piece.PieceType, piece.BWType, count);
                    count = 1;
                }
            }
        }
Пример #4
0
        /// <summary>
        /// 指し手をSFEN形式の文字列に変換します。
        /// </summary>
        /// <remarks>
        /// 筋に関しては1から9までの数字で表記され、段に関してはaからiまでの
        /// アルファベット(1段目がa、2段目がb、・・・、9段目がi)
        /// というように表記されます。位置の表記はこの2つを組み合わせ、
        /// 5一なら5a、1九なら1iとなります。
        ///
        /// 指し手に関しては、駒の移動元の位置と移動先の位置を並べて書きます。
        /// 7七の駒が7六に移動したのであれば、7g7fと表記します。
        /// (駒の種類を表記する必要はありません。)
        /// 駒が成るときは最後に+を追加します。8八の駒が2二に移動して
        /// 成るなら8h2b+です。
        /// 持ち駒を打つときは "[駒の種類(大文字)]*[打った場所]" となります。
        /// 金を5二に打つ場合はG*5bとなります
        /// </remarks>
        public static string ToSfen(this Move move)
        {
            if (move == null)
            {
                throw new ArgumentNullException("move");
            }

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

            if (move.IsSpecialMove)
            {
                // 投了などの特殊な指し手
                throw new SfenException(
                          move + ": sfenに変換することはできません。");
            }

            var dstFile = move.DstSquare.File;
            var dstRank = (char)((int)'a' + (move.DstSquare.Rank - 1));

            if (move.ActionType == ActionType.Drop)
            {
                // 駒打ちの場合
                var piece = SfenUtil.PieceTypeToSfen(move.DropPieceType);

                return(string.Format("{0}*{1}{2}",
                                     piece, dstFile, dstRank));
            }
            else
            {
                // 駒の移動の場合
                var srcFile   = move.SrcSquare.File;
                var srcRank   = (char)((int)'a' + (move.SrcSquare.Rank - 1));
                var isPromote = (move.ActionType == ActionType.Promote);

                return(string.Format("{0}{1}{2}{3}{4}",
                                     srcFile, srcRank, dstFile, dstRank,
                                     (isPromote ? "+" : "")));
            }
        }
Пример #5
0
        /// <summary>
        /// 持ち駒をSFEN形式に変換します。
        /// </summary>
        private static string HandToSfen(Board board)
        {
            var handList =
                from turn in new BWType[] { BWType.Black, BWType.White }
            from pieceType in EnumEx.GetValues <PieceType>()
            let obj = new
            {
                Piece = new BoardPiece(pieceType, false, turn),
                Count = board.GetHand(pieceType, turn),
            }
            where obj.Count > 0
            select string.Format("{0}{1}",
                                 (obj.Count > 1 ? obj.Count.ToString() : ""),
                                 SfenUtil.PieceToSfen(obj.Piece));

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

            return(array.Any() ? string.Join("", array) : "-");
        }
Пример #6
0
        /// <summary>
        /// 局面を読み込みます。
        /// </summary>
        private static void ParseBoard0(Board board, string sfen)
        {
            var rank     = 1;
            var file     = 9;
            var promoted = false;

            foreach (var c in sfen)
            {
                if (rank > 9)
                {
                    throw new SfenException(
                              "局面の段数が9を超えます。");
                }

                if (c == '/')
                {
                    if (file != 0)
                    {
                        throw new SfenException(
                                  "SFEN形式の" + rank + "段の駒数が合いません。");
                    }

                    rank    += 1;
                    file     = 9;
                    promoted = false;
                }
                else if (c == '+')
                {
                    promoted = true;
                }
                else if ('1' <= c && c <= '9')
                {
                    file    -= (c - '0');
                    promoted = false;
                }
                else
                {
                    if (file < 1)
                    {
                        throw new SfenException(
                                  "SFEN形式の" + rank + "段の駒数が多すぎます。");
                    }

                    var piece = SfenUtil.SfenToPiece(c);
                    if (piece == null)
                    {
                        throw new SfenException(
                                  "SFEN形式の駒'" + c + "'が正しくありません。");
                    }

                    var type = piece.PieceType;
                    if (promoted && type != PieceType.Gyoku && type != PieceType.Kin)
                    {
                        piece = new BoardPiece(piece.PieceType, promoted, piece.BWType);
                    }

                    board[file, rank] = piece;
                    file    -= 1;
                    promoted = false;
                }
            }

            if (file != 0)
            {
                throw new SfenException(
                          "SFEN形式の" + rank + "段の駒数が合いません。");
            }
        }
Пример #7
0
        /// <summary>
        /// SFEN形式の指し手を、指し手に変換します。
        /// </summary>
        public static Move SfenToMove(this Board board, string sfen)
        {
            if (board == null)
            {
                throw new ArgumentNullException("board");
            }

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

            if (sfen.Length < 4)
            {
                return(null);
            }

            var dropPieceType = SfenUtil.SfenToPieceType(sfen[0]);

            if (dropPieceType != PieceType.None)
            {
                // 駒打ちの場合
                if ((sfen[1] != '*') ||
                    (sfen[2] < '1' || '9' < sfen[2]) ||
                    (sfen[3] < 'a' || 'i' < sfen[3]))
                {
                    return(null);
                }

                var dstFile = (sfen[2] - '1') + 1;
                var dstRank = (sfen[3] - 'a') + 1;

                return(Move.CreateDrop(
                           board.Turn, new Square(dstFile, dstRank), dropPieceType));
            }
            else
            {
                // 駒の移動の場合
                if ((sfen[0] < '1' || '9' < sfen[0]) ||
                    (sfen[2] < '1' || '9' < sfen[2]) ||
                    (sfen[1] < 'a' || 'i' < sfen[1]) ||
                    (sfen[3] < 'a' || 'i' < sfen[3]))
                {
                    return(null);
                }

                var srcFile = (sfen[0] - '1') + 1;
                var srcRank = (sfen[1] - 'a') + 1;
                var dstFile = (sfen[2] - '1') + 1;
                var dstRank = (sfen[3] - 'a') + 1;
                var piece   = board[srcFile, srcRank];
                if (piece == null)
                {
                    return(null);
                }

                var promote = (sfen.Length > 4 && sfen[4] == '+');
                return(Move.CreateMove(
                           board.Turn,
                           new Square(srcFile, srcRank),
                           new Square(dstFile, dstRank),
                           piece.Piece,
                           promote,
                           BoardPiece.GetPiece(board[dstFile, dstRank])));
            }
        }