示例#1
0
        /// <summary>
        /// 駒の種類にかかわりなく、指定の位置に着手可能な指し手をすべて列挙します。
        /// </summary>
        public IEnumerable <BoardMove> ListupMoves(BWType bwType, Square dstSquare)
        {
            // 打てる駒をすべて列挙します。
            foreach (var pieceType in EnumEx.GetValues <PieceType>())
            {
                if (GetCapturedPieceCount(pieceType, bwType) <= 0)
                {
                    continue;
                }

                var move = BoardMove.CreateDrop(bwType, dstSquare, pieceType);

                // 駒打ちが可能なら、それも該当手となります。
                if (CanMove(move, MoveFlags.CheckOnly))
                {
                    yield return(move);
                }
            }

            // 移動による指し手をすべて列挙します。
            foreach (var srcSquare in Board.AllSquares())
            {
                var moves = GetAvailableMove(bwType, srcSquare, dstSquare);

                foreach (var move in moves)
                {
                    yield return(move);
                }
            }
        }
示例#2
0
        /// <summary>
        /// <paramref name="square"/>に<paramref name="pieceType"/>を打ち、
        /// なお王手されているか確認します。
        /// </summary>
        private bool IsDropAndChecked(BWType bwType, PieceType pieceType,
                                      Square square)
        {
            var piece = this[square];

            if (piece != null)
            {
                return(true);
            }

            var move = BoardMove.CreateDrop(bwType, square, pieceType);

            if (DoMove(move))
            {
                if (!IsChecked(bwType))
                {
                    Undo();
                    return(false);
                }
                Undo();

                return(true);
            }

            return(true);
        }
示例#3
0
        /// <summary>
        /// 駒を打つ手を生成します。
        /// </summary>
        public static Move CreateDrop(BWType turn, Square dst,
                                      PieceType dropPieceType)
        {
            if (turn == BWType.None)
            {
                throw new ArgumentException("turn");
            }

            if (dst == null || !dst.Validate())
            {
                throw new ArgumentException("dst");
            }

            if (dropPieceType == PieceType.None)
            {
                throw new ArgumentException("dropPieceType");
            }

            return(new Move
            {
                BWType = turn,
                DstSquare = dst,
                DropPieceType = dropPieceType,
            });
        }
示例#4
0
        /// <summary>
        /// ハッシュコードを取得します。
        /// </summary>
        public override int GetHashCode()
        {
            // ValueType.GetHashCodeは遅いらしい。。。
            if (IsSpecialMove)
            {
                return(SpecialMoveType.GetHashCode());
            }
            else
            {
                var baseHashCode =
                    BWType.GetHashCode() ^
                    SameAsOld.GetHashCode() ^
                    RelFileType.GetHashCode() ^
                    RankMoveType.GetHashCode() ^
                    ActionType.GetHashCode() ^
                    (Piece != null ? Piece.GetHashCode() : 0) ^
                    (SrcSquare != null ? SrcSquare.GetHashCode() : 0);

                if (SameAsOld)
                {
                    return(baseHashCode);
                }
                else
                {
                    return(
                        baseHashCode ^
                        File.GetHashCode() ^
                        Rank.GetHashCode());
                }
            }
        }
示例#5
0
 /// <summary>
 /// ハッシュ値を返します。
 /// </summary>
 public override int GetHashCode()
 {
     return(
         BWType.GetHashCode() ^
         PieceType.GetHashCode() ^
         IsPromoted.GetHashCode());
 }
示例#6
0
        /// <summary>
        /// 成るか不成りかダイアログによる選択を行います。
        /// </summary>
        private bool CheckToPromote(PieceType pieceType, BWType bwType)
        {
            var dialog    = new PromoteDialog();
            var screenPos = Cursor.Position;

            dialog.StartPosition = FormStartPosition.Manual;
            dialog.Left          = screenPos.X - (dialog.Width / 2);
            dialog.Top           = screenPos.Y - dialog.Height - (int)SquareSize.Height / 2;
            dialog.AdjustInDisplay();

            try
            {
                ClosePromoteDialog();

                // 成り・不成り選択中に外から局面が設定されることがあります。
                // その場合に備えてダイアログ自体を持っておきます。
                this.promoteDialog = dialog;

                var result = dialog.ShowDialog();
                ClosePromoteDialog();

                return(result == DialogResult.OK);
            }
            finally
            {
                ClosePromoteDialog();
            }
        }
示例#7
0
        private Board MakeBoard1(BWType turn)
        {
            /*
            後手の持駒:飛 桂 香 歩三
              9 8 7 6 5 4 3 2 1
            +---------------------------+
            |v香 ・ 龍 ・ ・ ・ ・ ・ ・|一
            | ・ ・ ・ ・v玉 ・ ・ ・ ・|二
            | ・ 香v歩 ・v金 ・v桂 ・ ・|三
            | ・ 歩v銀v銀v金 ・ ・ 銀 ・|四
            | 歩 ・ ・ ・ ・ 歩 歩 ・ ・|五
            | 香 ・ 歩 ・ 馬 ・ ・ ・v歩|六
            |v歩 ・ 桂 金 ・ ・ ・ ・ ・|七
            | ・ 玉 銀 金 ・ ・ 馬 ・ ・|八
            | ・ ・ ・ ・ ・ ・ ・ ・ ・|九
            +---------------------------+
            先手の持駒:桂 歩七
            */

            var turnCh = (turn == BWType.Black ? 'b' : 'w');
            var sfen =
                "l1+R6/4k4/1Lp1g1n2/1Pssg2S1/P4PP2/L1P1+B3p/p1NG5/1KSG2+B2/9" +
                " " + turnCh + " N7Prnl3p 1";
            var board = SfenBoard.Parse(sfen);

            Assert.NotNull(board);
            Assert.True(board.Validate());
            return board;
        }
示例#8
0
文件: Board.cs 项目: Shiiina/Ragnarok
        /// <summary>
        /// 駒を強制的に成る必要があるか調べます。
        /// </summary>
        public static bool IsPromoteForce(Piece piece, BWType bwType,
                                          Square dstSquare)
        {
            if (dstSquare == null || !dstSquare.Validate())
            {
                return(false);
            }

            // 駒の移動元に自分の駒がなければダメ
            if (piece == null || piece.IsPromoted)
            {
                return(false);
            }

            var normalizedRank = (
                bwType == BWType.White ?
                (BoardSize + 1) - dstSquare.Rank :
                dstSquare.Rank);

            if (piece.PieceType == PieceType.Kei)
            {
                return(normalizedRank <= 2);
            }
            else if (piece.PieceType == PieceType.Kyo ||
                     piece.PieceType == PieceType.Hu)
            {
                return(normalizedRank == 1);
            }

            return(false);
        }
示例#9
0
        /// <summary>
        /// <paramref name="srcSquare"/>の駒を<paramref name="dstSquare"/>
        /// に動かすことが可能な指し手をすべて列挙します。
        /// </summary>
        private IEnumerable<BoardMove> GetAvailableMove(BWType bwType,
                                                        Square srcSquare,
                                                        Square dstSquare)
        {
            var piece = this[srcSquare];
            if (piece == null || piece.BWType != bwType)
            {
                yield break;
            }

            var move = new BoardMove()
            {
                DstSquare = dstSquare,
                SrcSquare = srcSquare,
                MovePiece = piece.Piece,
                BWType = bwType,
            };

            // 成り駒でなければ、成る可能性があります。
            if (!piece.IsPromoted)
            {
                move.IsPromote = true;
                if (CanMove(move, MoveFlags.CheckOnly))
                {
                    // yield returnなのでCloneしないとまずい。
                    yield return move.Clone();
                }
            }

            move.IsPromote = false;
            if (CanMove(move, MoveFlags.CheckOnly))
            {
                yield return move;
            }
        }
示例#10
0
        /// <summary>
        /// 詰みになったときの手数をパースします。
        /// </summary>
        /// <example>
        /// +
        /// -10
        /// +5↑
        /// </example>
        public static Score ParseMate(string text, BWType turn)
        {
            if (string.IsNullOrEmpty(text))
            {
                throw new ArgumentNullException("text");
            }

            var trimmedText = text.Trim();
            var value = StringToInt(trimmedText);

            if (value == 0)
            {
                if (trimmedText[0] == '+')
                {
                    return new Score(turn, trimmedText, 0, true);
                }
                else if (trimmedText[0] == '-')
                {
                    return new Score(turn, trimmedText, 0, false);
                }
                else
                {
                    throw new ShogiException(
                        trimmedText + ": 詰み手数が正しくありません。");
                }
            }

            return new Score(turn, trimmedText, Math.Abs(value), (value > 0));
        }
示例#11
0
        /// <summary>
        /// 詰みになったときの手数をパースします。
        /// </summary>
        /// <example>
        /// +
        /// -10
        /// +5↑
        /// </example>
        public static Score ParseMate(string text, BWType turn)
        {
            if (string.IsNullOrEmpty(text))
            {
                throw new ArgumentNullException("text");
            }

            var trimmedText = text.Trim();
            var value       = StringToInt(trimmedText);

            if (value == 0)
            {
                if (trimmedText[0] == '+')
                {
                    return(new Score(turn, 0, true));
                }
                else if (trimmedText[0] == '-')
                {
                    return(new Score(turn, 0, false));
                }
                else
                {
                    //throw new ShogiException(
                    //    trimmedText + ": メイト手数が正しくありません。");

                    // 本来は先頭に+/-が必要ですが、そうなっていないソフトも多いので
                    // ここでは現状に合わせてエラーにはしないことにします。
                    return(new Score(turn, 0, true));
                }
            }

            return(new Score(turn, Math.Abs(value), (value > 0)));
        }
示例#12
0
        /// <summary>
        /// 駒の種類にかかわりなく、指定の位置に着手可能な指し手をすべて列挙します。
        /// </summary>
        public IEnumerable<BoardMove> ListupMoves(BWType bwType, Square dstSquare)
        {
            // 打てる駒をすべて列挙します。
            foreach (var pieceType in EnumEx.GetValues<PieceType>())
            {
                if (GetCapturedPieceCount(pieceType, bwType) <= 0)
                {
                    continue;
                }

                var move = new BoardMove()
                {
                    DstSquare = dstSquare,
                    DropPieceType = pieceType,
                    BWType = bwType,
                };

                // 駒打ちが可能なら、それも該当手となります。
                if (CanMove(move, MoveFlags.CheckOnly))
                {
                    yield return move;
                }
            }

            // 移動による指し手をすべて列挙します。
            foreach (var srcSquare in Board.AllSquares())
            {
                var moves = GetAvailableMove(bwType, srcSquare, dstSquare);

                foreach (var move in moves)
                {
                    yield return move;
                }
            }
        }
示例#13
0
        private Board MakeBoard1(BWType turn)
        {
            /*
             * 後手の持駒:飛 桂 香 歩三
             * 9 8 7 6 5 4 3 2 1
             +---------------------------+
             |v香 ・ 龍 ・ ・ ・ ・ ・ ・|一
             | ・ ・ ・ ・v玉 ・ ・ ・ ・|二
             | ・ 香v歩 ・v金 ・v桂 ・ ・|三
             | ・ 歩v銀v銀v金 ・ ・ 銀 ・|四
             | 歩 ・ ・ ・ ・ 歩 歩 ・ ・|五
             | 香 ・ 歩 ・ 馬 ・ ・ ・v歩|六
             |v歩 ・ 桂 金 ・ ・ ・ ・ ・|七
             | ・ 玉 銀 金 ・ ・ 馬 ・ ・|八
             | ・ ・ ・ ・ ・ ・ ・ ・ ・|九
             +---------------------------+
             | 先手の持駒:桂 歩七
             */

            var turnCh = (turn == BWType.Black ? 'b' : 'w');
            var sfen   =
                "l1+R6/4k4/1Lp1g1n2/1Pssg2S1/P4PP2/L1P1+B3p/p1NG5/1KSG2+B2/9" +
                " " + turnCh + " N7Prnl3p 1";
            var board = SfenBoard.Parse(sfen);

            Assert.NotNull(board);
            Assert.True(board.Validate());
            return(board);
        }
示例#14
0
 /// <summary>
 /// コンストラクタ
 /// </summary>
 public Score(BWType turn, string text = "", int value = 0)
 {
     ScoreType = ScoreType.Value;
     Turn      = turn;
     Text      = text;
     Value     = value;
 }
示例#15
0
        /// <summary>
        /// 詰みになったときの手数をパースします。
        /// </summary>
        /// <example>
        /// +
        /// -10
        /// +5↑
        /// </example>
        public static Score ParseMate(string text, BWType turn)
        {
            if (string.IsNullOrEmpty(text))
            {
                throw new ArgumentNullException("text");
            }

            var trimmedText = text.Trim();
            var value       = StringToInt(trimmedText);

            if (value == 0)
            {
                if (trimmedText[0] == '+')
                {
                    return(new Score(turn, trimmedText, 0, true));
                }
                else if (trimmedText[0] == '-')
                {
                    return(new Score(turn, trimmedText, 0, false));
                }
                else
                {
                    throw new ShogiException(
                              trimmedText + ": 詰み手数が正しくありません。");
                }
            }

            return(new Score(turn, trimmedText, Math.Abs(value), (value > 0)));
        }
示例#16
0
        /// <summary>
        /// 駒の種類と新しい位置から、可能な指し手をすべて検索します。
        /// </summary>
        public IEnumerable <Move> ListupMoves(Piece piece, BWType bwType,
                                              Square dstSquare)
        {
            // 打てる駒をすべて列挙します。
            if (!piece.IsPromoted && GetHand(piece.PieceType, bwType) > 0)
            {
                var move = Move.CreateDrop(bwType, dstSquare, piece.PieceType);

                // 駒打ちが可能なら、それも該当手となります。
                if (CanMove(move, MoveFlags.CheckOnly))
                {
                    yield return(move);
                }
            }

            // 移動による指し手をすべて列挙します。
            var srcRange = GetCanMoveRange(piece, dstSquare, bwType.Flip());

            foreach (var srcSquare in srcRange)
            {
                var moves = GetAvailableMove(piece, bwType, srcSquare, dstSquare);

                foreach (var move in moves)
                {
                    yield return(move);
                }
            }
        }
示例#17
0
        /// <summary>
        /// <paramref name="square"/>に<paramref name="pieceType"/>を打ち、
        /// なお王手されているか確認します。
        /// </summary>
        private bool IsDropAndChecked(BWType bwType, PieceType pieceType,
                                      Square square)
        {
            var piece = this[square];

            if (piece != null)
            {
                return(true);
            }

            var move = Move.CreateDrop(bwType, square, pieceType);

            if (DoMove(move, MoveFlags.DoMoveDefault & ~MoveFlags.CheckPawnDropCheckMate))
            {
                if (!IsChecked(bwType))
                {
                    Undo();
                    return(false);
                }
                Undo();

                return(true);
            }

            return(true);
        }
示例#18
0
        /// <summary>
        /// <paramref name="srcSquare"/>の駒を<paramref name="dstSquare"/>
        /// に動かすことが可能な指し手をすべて列挙します。
        /// </summary>
        private IEnumerable <Move> GetAvailableMove(Piece target,
                                                    BWType bwType,
                                                    Square srcSquare,
                                                    Square dstSquare)
        {
            var piece = this[srcSquare];

            if (piece == null || piece.Piece != target || piece.BWType != bwType)
            {
                yield break;
            }

            var move = Move.CreateMove(
                bwType, srcSquare, dstSquare, piece.Piece, false);

            // 成り駒でなければ、成る可能性があります。
            if (!piece.IsPromoted)
            {
                move.IsPromote = true;
                if (CanMove(move, MoveFlags.CheckOnly))
                {
                    // yield returnなのでCloneしないとまずい。
                    yield return(move.Clone());
                }
            }

            move.IsPromote = false;
            if (CanMove(move, MoveFlags.CheckOnly))
            {
                yield return(move);
            }
        }
示例#19
0
 /// <summary>
 /// 駒の種類と新しい位置から、可能な指し手をすべて検索します。
 /// </summary>
 public IEnumerable <BoardMove> ListupMoves(Piece piece, BWType bwType,
                                            Square dstSquare)
 {
     return(ListupMoves(bwType, dstSquare)
            .Where(_ =>
                   (_.MovePiece == piece) ||
                   (_.DropPieceType == piece.PieceType && !piece.IsPromoted)));
 }
示例#20
0
 /// <summary>
 /// 駒の種類と新しい位置から、可能な指し手をすべて検索します。
 /// </summary>
 public IEnumerable<BoardMove> ListupMoves(Piece piece, BWType bwType,
                                           Square dstSquare)
 {
     return ListupMoves(bwType, dstSquare)
         .Where(_ =>
             (_.MovePiece == piece) ||
             (_.DropPieceType == piece.PieceType && !piece.IsPromoted));
 }
示例#21
0
 /// <summary>
 /// コンストラクタ
 /// </summary>
 public Score(BWType turn, int value = 0,
              ScoreBound bound       = ScoreBound.Exact)
 {
     ScoreType  = ScoreType.Value;
     ScoreBound = bound;
     Turn       = turn;
     Value      = value;
 }
示例#22
0
        /// <summary>
        /// テーブルを使用し、指定の相対位置に動けるか調べます。(先手専用)
        /// </summary>
        private bool CanMoveWithTable(BWType bwType, int relFile, int relRank,
                                      int[][] table)
        {
            // 後手側なら上下反転します。
            var sign = (bwType == BWType.White ? -1 : +1);

            relRank *= sign;
            return table.Any(_ => relFile == _[0] && relRank == _[1]);
        }
示例#23
0
        /// <summary>
        /// 持ち駒の数を減らします。
        /// </summary>
        public void DecCapturedPieceCount(PieceType pieceType, BWType bwType)
        {
            using (LazyLock())
            {
                var capturedPiece = GetCapturedPieceBox(bwType);

                capturedPiece.Decrement(pieceType);
            }
        }
示例#24
0
文件: Board.cs 项目: Shiiina/Ragnarok
 /// <summary>
 /// 指定の筋にある歩の数を確認します。
 /// </summary>
 public int GetPawnCount(BWType bwType, int file)
 {
     return(Enumerable.Range(1, BoardSize)
            .Select(_ => this[file, _])
            .Where(_ => _ != null)
            .Where(_ => _.Piece == Piece.Hu)
            .Where(_ => _.BWType == bwType)
            .Count());
 }
示例#25
0
        /// <summary>
        /// 局面と表示で駒台の駒の数を合わせます。
        /// </summary>
        private void SyncCapturedPieceCount(PieceType pieceType, BWType bwType)
        {
            var piece = GetCapturedPieceObject(pieceType, bwType);

            if (piece != null)
            {
                piece.Count = GetCapturedPieceCount(pieceType, bwType);
            }
        }
示例#26
0
 /// <summary>
 /// コンストラクタ
 /// </summary>
 public Score(BWType turn, int mate, bool isMateWin)
 {
     ScoreType  = ScoreType.Mate;
     ScoreBound = ScoreBound.Exact;
     Turn       = turn;
     Mate       = mate;
     IsMateWin  = isMateWin;
     Value      = (isMateWin ? MateScore : -MateScore);
 }
示例#27
0
        /// <summary>
        /// 持ち駒の数を取得します。
        /// </summary>
        public int GetCapturedPieceCount(PieceType pieceType, BWType bwType)
        {
            using (LazyLock())
            {
                var capturedPiece = GetCapturedPieceBox(bwType);

                return(capturedPiece.GetCount(pieceType));
            }
        }
示例#28
0
        /// <summary>
        /// テーブルを使用し、指定の相対位置に動けるか調べます。(先手専用)
        /// </summary>
        private bool CanMoveWithTable(BWType bwType, int relFile, int relRank,
                                      int[][] table)
        {
            // 後手側なら上下反転します。
            var sign = (bwType == BWType.White ? -1 : +1);

            relRank *= sign;
            return(table.Any(_ => relFile == _[0] && relRank == _[1]));
        }
示例#29
0
 /// <summary>
 /// 指定の筋にある歩の数を取得します。
 /// </summary>
 private int GetHuCountOfFile(int file, BWType bwType)
 {
     return(Enumerable.Range(1, BoardSize)
            .Select(_ => this[file, _])
            .Where(_ => _ != null)
            .Where(_ => _.Piece == Piece.Hu)
            .Where(_ => _.BWType == bwType)
            .Count());
 }
示例#30
0
 /// <summary>
 /// コンストラクタ
 /// </summary>
 public Score(BWType turn, string text, int mate, bool isMateWin)
 {
     ScoreType = ScoreType.Mate;
     Turn      = turn;
     Text      = text;
     Mate      = mate;
     IsMateWin = isMateWin;
     Value     = (isMateWin ? MateScore : -MateScore);
 }
示例#31
0
        /// <summary>
        /// 手番をSFEN形式に変換します。
        /// </summary>
        private static string TurnToSfen(BWType turn)
        {
            if (turn == BWType.None)
            {
                throw new SfenException(
                          "局面の手番が正しくありません。");
            }

            return(turn == BWType.Black ? "b" : "w");
        }
示例#32
0
        /// <summary>
        /// 駒台上の表示用の駒を取得します。
        /// </summary>
        private PieceObject GetCapturedPieceObject(PieceType pieceType, BWType bwType)
        {
            var index             = GetCapturedPieceIndex(bwType, BWType.Black);
            var capturedPieceList = this.capturedPieceObjectList[index];

            return(
                (int)pieceType < capturedPieceList.Count ?
                capturedPieceList[(int)pieceType] :
                null);
        }
示例#33
0
        /// <summary>
        /// 手番をCSA形式に変換します。
        /// </summary>
        private static string TurnToCsa(BWType turn)
        {
            if (turn == BWType.None)
            {
                throw new CsaException(
                    "局面の手番が正しくありません。");
            }

            return (turn == BWType.Black ? "+" : "-");
        }
示例#34
0
        /// <summary>
        /// 持ち駒の数を設定します。
        /// </summary>
        public void SetCapturedPieceCount(PieceType pieceType, BWType bwType,
                                          int count)
        {
            using (LazyLock())
            {
                var capturedPiece = GetCapturedPieceBox(bwType);

                capturedPiece.SetCount(pieceType, count);
            }
        }
示例#35
0
 /// <summary>
 /// 駒の種類にかかわりなく、指定の位置に着手可能な指し手をすべて列挙します。
 /// </summary>
 public IEnumerable <Move> ListupMoves(BWType bwType, Square dstSquare)
 {
     return
         (from type in EnumEx.GetValues <PieceType>()
          where type != PieceType.None
          from promoted in new bool[] { true, false }
          let piece = new Piece(type, promoted)
                      from move in ListupMoves(piece, bwType, dstSquare)
                      select move);
 }
示例#36
0
        /// <summary>
        /// 手番をCSA形式に変換します。
        /// </summary>
        private static string TurnToCsa(BWType turn)
        {
            if (turn == BWType.None)
            {
                throw new CsaException(
                          "局面の手番が正しくありません。");
            }

            return(turn == BWType.Black ? "+" : "-");
        }
示例#37
0
文件: Board.cs 项目: Shiiina/Ragnarok
 /// <summary>
 /// 持ち駒の数を取得します。
 /// </summary>
 public Hand GetHand(BWType bwType)
 {
     if (bwType == BWType.Black)
     {
         return(this.blackHandBox);
     }
     else
     {
         return(this.whiteHandBox);
     }
 }
示例#38
0
        /// <summary>
        /// 通常の評価値をパースします。
        /// </summary>
        /// <example>
        /// 0
        /// -98
        /// +456↑
        /// </example>
        public static Score ParseValue(string text, BWType turn)
        {
            if (string.IsNullOrEmpty(text))
            {
                throw new ArgumentNullException("text");
            }

            var trimmedText = text.Trim();
            var value = StringToInt(trimmedText);

            return new Score(turn, trimmedText, value);
        }
示例#39
0
        /// <summary>
        /// テーブルを使用し、指定の相対位置に動けるか調べます。(先手専用)
        /// </summary>
        private IEnumerable<Square> GetMoveRangeWithTable(BWType bwType,
                                                          Square square,
                                                          int[][] table)
        {
            // 後手側なら上下反転します。
            var sign = (bwType == BWType.White ? -1 : +1);

            foreach (var elem in table)
            {
                var sq = new Square(
                    square.File + elem[0],
                    square.Rank + elem[1] * sign);

                if (sq.Validate())
                {
                    yield return sq;
                }
            }
        }
示例#40
0
        /// <summary>
        /// CSA形式の局面を1行ごと読み込んでみます。
        /// </summary>
        public bool TryParse(string line)
        {
            if (string.IsNullOrEmpty(line))
            {
                throw new ArgumentNullException("line");
            }

            var trimmedLine = line.TrimEnd('\r', '\n');

            // 手番読み取り
            var ch0 = trimmedLine[0];
            if (trimmedLine.Length == 1 && (ch0 == '+' || ch0 == '-'))
            {
                this.turn = (ch0 == '+' ? BWType.Black : BWType.White);
                return true;
            }

            // 各形式の局面読み取り
            if (ch0 == 'P' && trimmedLine.Length >= 2)
            {
                var ch1 = trimmedLine[1];
                if (ch1 == 'I')
                {
                    ParseBoardPI(trimmedLine);
                    return true;
                }

                if (ch1 == '+' || ch1 == '-')
                {
                    ParseBoardP(trimmedLine);
                    return true;
                }

                if ('1' <= ch1 && ch1 <= '9')
                {
                    ParseBoardPn(trimmedLine);
                    return true;
                }
            }

            return false;
        }
示例#41
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);
                
                count = int.Parse(normalized);
            }

            return Tuple.Create(piece.PieceType, count);
        }
示例#42
0
        /// <summary>
        /// <paramref name="square"/>にある駒が移動できる
        /// 可能性のある位置をすべて列挙します。
        /// </summary>
        private IEnumerable<Square> GetCanMoveRange(Square square, BWType bwType)
        {
            if (square == null || !square.Validate())
            {
                yield break;
            }

            var piece = this[square];
            if (piece == null || piece.BWType != bwType)
            {
                yield break;
            }

            IEnumerable<Square> list;
            var file = square.File;
            var rank = square.Rank;

            using (LazyLock())
            {
                if (piece.IsPromoted)
                {
                    // 成り駒の場合
                    switch (piece.PieceType)
                    {
                        case PieceType.Gyoku:
                        case PieceType.Hisya:
                        case PieceType.Kaku:
                            list = GetMoveRangeWithTable(bwType, square, MoveTableGyoku);
                            foreach (var p in list)
                            {
                                yield return p;
                            }
                            break;
                        case PieceType.Kin:
                        case PieceType.Gin:
                        case PieceType.Kei:
                        case PieceType.Kyo:
                        case PieceType.Hu:
                            list = GetMoveRangeWithTable(bwType, square, MoveTableKin);
                            foreach (var p in list)
                            {
                                yield return p;
                            }
                            break;
                    }
                }
                else
                {
                    // 成り駒で無い場合
                    switch (piece.PieceType)
                    {
                        case PieceType.Gyoku:
                            list = GetMoveRangeWithTable(bwType, square, MoveTableGyoku);
                            foreach (var p in list)
                            {
                                yield return p;
                            }
                            break;
                        case PieceType.Kin:
                            list = GetMoveRangeWithTable(bwType, square, MoveTableKin);
                            foreach (var p in list)
                            {
                                yield return p;
                            }
                            break;
                        case PieceType.Gin:
                            list = GetMoveRangeWithTable(bwType, square, MoveTableGin);
                            foreach (var p in list)
                            {
                                yield return p;
                            }
                            break;
                        case PieceType.Kei:
                            list = GetMoveRangeWithTable(bwType, square, MoveTableKei);
                            foreach (var p in list)
                            {
                                yield return p;
                            }
                            break;
                        case PieceType.Hu:
                            list = GetMoveRangeWithTable(bwType, square, MoveTableHu);
                            foreach (var p in list)
                            {
                                yield return p;
                            }
                            break;
                        case PieceType.Kyo:
                            for (var r = 1; r <= BoardSize; ++r)
                            {
                                yield return new Square(file, r);
                            }
                            break;
                    }
                }

                // 飛車角は成り/不成りに関わらず調べる箇所があります。
                switch (piece.PieceType)
                {
                    case PieceType.Hisya:
                        for (var f = 1; f <= BoardSize; ++f)
                        {
                            if (piece.IsPromoted && Math.Abs(file - f) <= 1)
                            {
                                continue;
                            }

                            var sq = new Square(f, rank);
                            if (sq.Validate())
                            {
                                yield return sq;
                            }
                        }
                        for (var r = 1; r <= BoardSize; ++r)
                        {
                            if (piece.IsPromoted && Math.Abs(rank - r) <= 1)
                            {
                                continue;
                            }

                            var sq = new Square(file, r);
                            if (sq.Validate())
                            {
                                yield return sq;
                            }
                        }
                        break;

                    case PieceType.Kaku:
                        for (var index = -BoardSize; index <= BoardSize; ++index)
                        {
                            if (piece.IsPromoted && Math.Abs(index) <= 1)
                            {
                                continue;
                            }

                            var sq = new Square(file + index, rank + index);
                            if (sq.Validate())
                            {
                                yield return sq;
                            }
                        }
                        for (var index = -BoardSize; index <= BoardSize; ++index)
                        {
                            if (piece.IsPromoted && Math.Abs(index) <= 1)
                            {
                                continue;
                            }

                            var sq = new Square(file + index, rank - index);
                            if (sq.Validate())
                            {
                                yield return sq;
                            }
                        }
                        break;
                }
            }
        }
示例#43
0
 /// <summary>
 /// 持ち駒や駒箱の駒の数を増やします。
 /// </summary>
 private void IncHandCount(PieceType pieceType, BWType bwType)
 {
     SetHandCount(
         pieceType, bwType,
         GetHandCount(pieceType, bwType) + 1);
 }
示例#44
0
        /// <summary>
        /// 成るか不成りかダイアログによる選択を行います。
        /// </summary>
        private bool CheckToPromote(PieceType pieceType, BWType bwType)
        {
            var dialog = new PromoteDialog();
            var screenPos = Cursor.Position;

            dialog.StartPosition = FormStartPosition.Manual;
            dialog.Left = screenPos.X - (dialog.Width / 2);
            dialog.Top = screenPos.Y - dialog.Height - (int)SquareSize.Height / 2;
            dialog.AdjustInDisplay();

            try
            {
                ClosePromoteDialog();

                // 成り・不成り選択中に外から局面が設定されることがあります。
                // その場合に備えてダイアログ自体を持っておきます。
                this.promoteDialog = dialog;

                var result = dialog.ShowDialog();
                ClosePromoteDialog();

                return (result == DialogResult.OK);
            }
            finally
            {
                ClosePromoteDialog();
            }
        }
示例#45
0
 /// <summary>
 /// コンストラクタ
 /// </summary>
 public Score(BWType turn, string text = "", int value = 0)
 {
     ScoreType = ScoreType.Value;
     Turn = turn;
     Text = text;
     Value = value;
 }
示例#46
0
 /// <summary>
 /// 手番を内部インデックスに変換します。(局面の反転を考慮します)
 /// </summary>
 private static int GetPieceBoxIndex(BWType bwType, BWType viewSide)
 {
     if (bwType == BWType.None)
     {
         return 0;
     }
     else if (bwType == viewSide)
     {
         return 1;
     }
     else
     {
         return 2;
     }
 }
示例#47
0
        /// <summary>
        /// 駒台上の駒のデフォルト中心位置を取得します。
        /// </summary>
        public PointF HandPieceToPoint(PieceType pieceType, BWType bwType)
        {
            var index = GetPieceBoxIndex(bwType, ViewSide);
            var bounds = this.pieceBoxBounds[index];

            // ○ 駒位置の計算方法
            // 駒台には駒を横に2つ並べます。また、両端と駒と駒の間には
            // 駒の幅/2をスペースとして挿入します。
            // このため、駒の幅/2 を基本区間とし、
            //   2(両端) + 1(駒間) + 4(駒数*2) = 7
            // を区間数として、駒の位置を計算します。
            //
            // また、縦の計算では先手・後手などの文字列を表示するため、
            // 手前側は上部、向かい側は下部に余計な空間を作ります。
            //   4(上下端+α) + 3(駒間) + 8(駒数*4) = 15
            var hw = bounds.Width / 7;
            var hh = bounds.Height / 15;
            var x = ((int)pieceType - 2) % 2;
            var y = ((int)pieceType - 2) / 2;
            var offsetY = 0.0f;

            // 駒箱の玉も表示します。
            if (pieceType == PieceType.Gyoku)
            {
                x = 1;
                y = 3;
            }

            if (bwType == BWType.None || bwType == ViewSide)
            {
                offsetY = 1.9f;
            }
            else
            {
                x = 1 - x;
                y = 3 - y;
                offsetY = 0.3f;
            }

            // 駒の中心位置
            // 駒の数を右肩に表示するため、少し左にずらしています。
            // また、対局者名などを表示するため上下にずらしています。
            return new PointF(
                bounds.Left + hw * (x * 3 + 2 - 0.2f),
                bounds.Top + hh * (y * 3 + 2 + offsetY));
        }
示例#48
0
        /// <summary>
        /// 駒の移動などを開始できるかどうか調べます。
        /// </summary>
        private bool CanBeginMove(BWType pieceSide)
        {
            if (this.movingPiece != null)
            {
                return false;
            }

            if (this.autoPlay != null)
            {
                return false;
            }

            var turn = (Board != null ? Board.Turn : BWType.None);
            if ((EditMode == EditMode.NoEdit) ||
                (EditMode == EditMode.Normal && turn != pieceSide))
            {
                return false;
            }

            return true;
        }
示例#49
0
        /// <summary>
        /// 編集モードでの駒の移動を行います。
        /// </summary>
        /// <remarks>
        /// 駒の移動元・移動先は
        /// ・盤面上のマス
        /// ・駒台 or 駒箱
        /// の2種類があります。
        /// </remarks>
        private void DoMoveEditing(Square dstSquare, BWType? boxColor)
        {
            var piece = this.movingPiece.BoardPiece;
            var srcSquare = this.movingPiece.Square;

            if (dstSquare == null && boxColor == null)
            {
                throw new ArgumentException("DoMoveEditing");
            }

            // 駒箱から持ってきた場合は先手番の駒として置きます。
            var bwType = (
                piece.BWType == BWType.None ?
                ViewSide : piece.BWType);

            // 先に盤面の状態を元に戻しておきます。
            EndMove();

            // 盤上に駒を動かす場合は、2歩を禁止する必要があります。
            if (dstSquare != null && piece.Piece == Piece.Hu)
            {
                // 同じ筋に動かす場合は2歩の判定を行いません。
                if ((srcSquare == null || dstSquare.File != srcSquare.File) &&
                    (Board.IsDoublePawn(bwType, dstSquare)))
                {
                    return;
                }
            }

            if (dstSquare != null &&
                Board.IsPromoteForce(piece.Piece, piece.BWType, dstSquare))
            {
                piece.IsPromoted = true;
            }

            // 移動元の駒の消去
            if (srcSquare != null)
            {
                // 盤上の移動前にあった駒を削除します。
                Board[srcSquare] = null;
            }
            else
            {
                // 駒箱などの駒の数を減らします。
                DecHandCount(piece.PieceType, piece.BWType);
            }
            
            if (boxColor != null)
            {
                // 駒箱へ移動する場合
                IncHandCount(piece.PieceType, boxColor.Value);
            }
            else if (dstSquare != null)
            {
                // 移動先が盤上の場合
                var target = Board[dstSquare];
                if (target != null)
                {
                    IncHandCount(target.PieceType, piece.BWType);

                    Board[dstSquare] = null;
                }

                // 移動先の駒を増やします。
                Board[dstSquare] =
                    new BoardPiece(piece.PieceType, piece.IsPromoted, bwType);
            }
        }
示例#50
0
        /// <summary>
        /// 香車が指定の場所に動けるか判断します。
        /// </summary>
        private bool CanMoveKyo(BWType bwType, Square basePos, int relFile, int relRank)
        {
            // 香車は横には動けません。
            if (relFile != 0)
            {
                return false;
            }

            // 反対方向には動けません。
            if ((bwType == BWType.Black && relRank >= 0) ||
                (bwType == BWType.White && relRank <= 0))
            {
                return false;
            }

            var destRank = basePos.Rank + relRank;
            var addRank = (relRank >= 0 ? +1 : -1);

            // 基準点には自分がいるので、とりあえず一度は
            // 駒の位置をズラしておきます。
            var baseFile = basePos.File;
            var baseRank = basePos.Rank + addRank;

            // 駒を動かしながら、目的地まで動かします。
            // 動かす途中に何か駒があれば、目的地へは動けません。
            while (baseRank != destRank)
            {
                // 自分の駒があっても相手の駒があってもダメです。
                if (this[baseFile, baseRank] != null)
                {
                    return false;
                }

                baseRank += addRank;
            }

            return true;
        }
示例#51
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));
            }
        }
示例#52
0
        /// <summary>
        /// 持ち駒を読み込みます。
        /// </summary>
        /// <example>
        /// 後手の持駒:飛 角 金 銀 桂 香 歩四 
        /// </example>
        private void ParseHand(BWType bwType, string handText)
        {
            if (handText == "なし")
            {
                return;
            }

            // 持ち駒をまとめて設定します。
            handText
                .Split(new char[] { ' ', ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries)
                .Select(_ => ParseHandPiece(bwType, _))
                .ForEach(_ => this.board.SetCapturedPieceCount(_.Item1, bwType, _.Item2));
        }
示例#53
0
        /// <summary>
        /// <paramref name="square"/>に<paramref name="pieceType"/>を打ち、
        /// なお王手されているか確認します。
        /// </summary>
        private bool IsDropAndChecked(BWType bwType, PieceType pieceType,
                                      Square square)
        {
            var piece = this[square];
            if (piece != null)
            {
                return true;
            }

            var move = new BoardMove()
            {
                DstSquare = square,
                DropPieceType = pieceType,
                BWType = bwType,
            };
            if (DoMove(move))
            {
                if (!IsChecked(bwType))
                {
                    Undo();
                    return false;
                }
                Undo();

                return true;
            }

            return true;
        }
示例#54
0
        /// <summary>
        /// <paramref name="bwType"/>側の玉が王手されているか調べます。
        /// </summary>
        public bool IsChecked(BWType bwType)
        {
            var gyoku = GetGyoku(bwType);
            if (gyoku == null || !gyoku.Validate())
            {
                return false;
            }

            // 玉の位置に移動できる駒があれば王手されています。
            return ListupMoves(bwType.Flip(), gyoku).Any();
        }
示例#55
0
        /// <summary>
        /// 玉のいる位置を取得します。
        /// </summary>
        public Square GetGyoku(BWType bwType)
        {
            var list =
                from sq in Board.AllSquares()
                let piece = this[sq]
                where piece != null
                where piece.PieceType == PieceType.Gyoku
                where piece.BWType == bwType
                select sq;

            return list.FirstOrDefault();
        }
示例#56
0
 /// <summary>
 /// 強制的に手番を設定します。
 /// </summary>
 private void SetTurn(BWType bwType)
 {
     this.board.Turn = bwType;
     this.turnHandled = true;
 }
示例#57
0
        /// <summary>
        /// <paramref name="srcSquare"/>の駒を<paramref name="dstSquare"/>
        /// に動かすことが可能な指し手を指してみて、なお王手されているか確認します。
        /// </summary>
        private bool IsMoveAndChecked(BWType bwType, Square srcSquare,
                                      Square dstSquare)
        {
            var piece = this[srcSquare];
            if (piece == null || piece.BWType != bwType)
            {
                return true;
            }

            var move = new BoardMove()
            {
                DstSquare = dstSquare,
                SrcSquare = srcSquare,
                MovePiece = piece.Piece,
                BWType = bwType,
            };

            // 成り駒でなければ、成る可能性があります。
            if (!piece.IsPromoted)
            {
                move.IsPromote = true;
                if (DoMove(move))
                {
                    if (!IsChecked(bwType))
                    {
                        Undo();
                        return false;
                    }
                    Undo();

                    return true;
                }
            }

            move.IsPromote = false;
            if (DoMove(move))
            {
                if (!IsChecked(bwType))
                {
                    Undo();
                    return false;
                }
                Undo();

                return true;
            }

            return true;
        }
示例#58
0
 /// <summary>
 /// 手番を△や▲に変換します。
 /// </summary>
 public static string ToString(BWType bwType)
 {
     return BWTypeTable[bwType];
 }
示例#59
0
 /// <summary>
 /// コンストラクタ
 /// </summary>
 public Score(BWType turn, string text, int mate, bool isMateWin)
 {
     ScoreType = ScoreType.Mate;
     Turn = turn;
     Text = text;
     Mate = mate;
     IsMateWin = isMateWin;
     Value = (isMateWin ? MateScore : -MateScore);
 }
示例#60
0
 /// <summary>
 /// 持ち駒や駒箱の駒の数を減らします。
 /// </summary>
 private void DecHandCount(PieceType pieceType, BWType bwType)
 {
     SetHandCount(
         pieceType, bwType,
         GetHandCount(pieceType, bwType) - 1);
 }