Exemple #1
0
        /// <summary>
        /// 上、引、寄るの判定をします。
        /// </summary>
        private static bool CheckRankMoveType(BoardMove bm,
                                              Move referenceMove)
        {
            if (bm.ActionType == ActionType.Drop)
            {
                return(false);
            }

            var fileMove = bm.DstSquare.File - bm.SrcSquare.File;
            var rankMove = bm.DstSquare.Rank - bm.SrcSquare.Rank;

            switch (referenceMove.RankMoveType)
            {
            case RankMoveType.Back:
                return(bm.BWType == BWType.Black
                                ? (rankMove > 0)
                                : (rankMove < 0));

            case RankMoveType.Up:
                return(bm.BWType == BWType.Black
                                ? (rankMove < 0)
                                : (rankMove > 0));

            case RankMoveType.Sideways:
                return(fileMove != 0 && rankMove == 0);
            }

            return(false);
        }
Exemple #2
0
        /// <summary>
        /// 1手指したときに呼ばれます。
        /// </summary>
        private void MoveDone(BoardMove move)
        {
            NotifyBoardChanging(move, false);

            // 特殊な指し手の場合は手番などの入れ替えを行いません。
            // (投了後の局面から駒を移動するため)
            if (!move.IsSpecialMove)
            {
                Turn            = Turn.Flip();
                PrevMovedSquare = move.DstSquare;
            }

            this.moveList.Add(move);

            // リドゥスタックの更新を行います。
            var redoMove = this.redoList.LastOrDefault();

            if (redoMove != null && redoMove.Equals(move))
            {
                // 指し手がリドゥと同じなら手を一つ削るだけです。
                this.redoList.RemoveAt(this.redoList.Count - 1);
            }
            else
            {
                this.redoList.Clear();
            }

            // 局面の変化を通知します。
            NotifyBoardChanged(move, false);
        }
Exemple #3
0
        /// <summary>
        /// バイト列から指し手リストを取得します。
        /// </summary>
        private List <BoardMove> DeserializeMoveList(byte[] moveListBytes)
        {
            // 指し手が無い場合、配列はnullになります。
            if (moveListBytes == null)
            {
                return(new List <BoardMove>());
            }

            var result = new List <BoardMove>(moveListBytes.Count() / 4);

            for (var i = 0; i < moveListBytes.Count(); i += 4)
            {
                var bits = (
                    (moveListBytes[i + 0] << 0) |
                    (moveListBytes[i + 1] << 8) |
                    (moveListBytes[i + 2] << 16) |
                    (moveListBytes[i + 3] << 24));

                var boardMove = new BoardMove();
                boardMove.Deserialize((uint)bits);

                result.Add(boardMove);
            }

            return(result);
        }
Exemple #4
0
        /// <summary>
        /// 打つ、成る、成らず、などを判定します。
        /// </summary>
        /// <remarks>
        /// 駒が指定の場所に移動できない場合は自動的に打つが選ばれます。
        /// (盤上に飛車がないのに、"32飛車"のときなど)
        /// </remarks>
        private static bool CheckActionType(BoardMove bm,
                                            Move referenceMove, bool canMove)
        {
            if (referenceMove.ActionType == ActionType.None)
            {
                // 指し手一覧の中に移動できる駒があれば、
                // 「打」と指定しなければ打つと判定されません。
                if (canMove)
                {
                    // 指定無しと成らずでおkとします。
                    return(
                        bm.ActionType == ActionType.None ||
                        bm.ActionType == ActionType.Unpromote);
                }
                else
                {
                    return(
                        bm.ActionType == ActionType.None ||
                        bm.ActionType == ActionType.Unpromote ||
                        bm.ActionType == ActionType.Drop);
                }
            }
            else if (referenceMove.ActionType == ActionType.Unpromote)
            {
                // 「不成」の場合は無と成らずでおkとします。
                return(
                    bm.ActionType == ActionType.None ||
                    bm.ActionType == ActionType.Unpromote);
            }

            return(bm.ActionType == referenceMove.ActionType);
        }
Exemple #5
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);
                }
            }
        }
Exemple #6
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 = BoardMove.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);
            }
        }
Exemple #7
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);
        }
Exemple #8
0
        /// <summary>
        /// 複数ある指し手の中から、適切なひとつの指し手を選択します。
        /// </summary>
        /// <remarks>
        /// <paramref name="referenceMove"/>にはXからYに移動したという情報
        /// しかないため、これを52金右などの指し手に変換します。
        /// </remarks>
        private static Move FilterMove(this Board board,
                                       List <BoardMove> boardMoveList,
                                       BoardMove referenceMove,
                                       Piece fromPiece,
                                       bool useSrcSquare)
        {
            if (!boardMoveList.Any())
            {
                return(null);
            }

            var nextPos = referenceMove.DstSquare;
            var move    = new Move
            {
                BWType     = referenceMove.BWType,
                Piece      = fromPiece,
                File       = nextPos.File,
                Rank       = nextPos.Rank,
                ActionType = ( // '打', '不成'は消える可能性があります。
                    referenceMove.ActionType == ActionType.Promote ?
                    referenceMove.ActionType :
                    ActionType.None),
                SameAsOld = (board.PrevMovedSquare == nextPos),
            };

            // 移動元情報を使う場合は、これで終わりです。
            // (.kifファイルからの読み込み時は、駒の移動の場合は移動前情報がつき、
            //  駒打ちの場合は"打"が必ずつきます)
            if (useSrcSquare)
            {
                move.SrcSquare  = referenceMove.SrcSquare;
                move.ActionType = referenceMove.ActionType;
                return(move);
            }

            // 駒打ち、成り、不成りなどでフィルターします。
            var tmpMoveList = FilterAction(move, referenceMove, boardMoveList);

            if (!tmpMoveList.Any())
            {
                return(null);
            }

            // 段の位置でフィルターします。
            tmpMoveList = FilterRank(move, referenceMove, tmpMoveList);
            if (!tmpMoveList.Any())
            {
                return(null);
            }

            // 列の位置でフィルターします。
            tmpMoveList = FilterFile(move, referenceMove, tmpMoveList);
            if (!tmpMoveList.Any())
            {
                return(null);
            }

            return(move);
        }
Exemple #9
0
        /// <summary>
        /// 特殊な指し手の着手が行えるか調べ、必要なら実行します。
        /// </summary>
        private bool CheckAndMakeSpecialMove(BoardMove move, MoveFlags flags)
        {
            if (!EnumEx.HasFlag(flags, MoveFlags.CheckOnly))
            {
                MoveDone(move);
            }

            return(true);
        }
Exemple #10
0
        /// <summary>
        /// 駒を強制的に成る必要があるか調べます。
        /// </summary>
        public static bool IsPromoteForce(BoardMove move)
        {
            if (move == null)
            {
                throw new ArgumentNullException("move");
            }

            return(IsPromoteForce(move.MovePiece, move.BWType, move.DstSquare));
        }
Exemple #11
0
        /// <summary>
        /// 段で指し手をフィルターし、Moveに適切なRankMoveTypeを設定します。
        /// </summary>
        private static List <BoardMove> FilterRank(Move move,
                                                   BoardMove referenceMove,
                                                   List <BoardMove> boardMoveList)
        {
            // 駒の移動前情報が必要です。
            var nextPos = referenceMove.DstSquare;
            var prevPos = referenceMove.SrcSquare;

            if (prevPos == null)
            {
                // 何もフィルターしません。
                return(boardMoveList);
            }

            // 黒から見ると正の場合は引く or 左へ移動(右)で
            // 負の場合は上がる or 右へ移動(左)です。
            var relRank = nextPos.Rank - prevPos.Rank;

            // 段の位置でフィルターします。
            var tmpMoveList = boardMoveList.Where(mv =>
            {
                var rel = nextPos.Rank - mv.SrcSquare.Rank;
                if (relRank < 0)
                {
                    return(rel < 0);
                }
                else if (relRank > 0)
                {
                    return(rel > 0);
                }
                else
                {
                    return(rel == 0);
                }
            }).ToList();

            // 段情報でフィルターされた場合は、段の移動情報を付加します。
            if (tmpMoveList.Count() != boardMoveList.Count())
            {
                var relRank2 = relRank * referenceMove.BWType.Sign();

                if (relRank2 < 0)
                {
                    move.RankMoveType = RankMoveType.Up;
                }
                else if (relRank2 > 0)
                {
                    move.RankMoveType = RankMoveType.Back;
                }
                else
                {
                    move.RankMoveType = RankMoveType.Sideways;
                }
            }

            return(tmpMoveList);
        }
Exemple #12
0
        /// <summary>
        /// 局面の変更直前の通知を出します。
        /// </summary>
        private void NotifyBoardChanging(BoardMove move, bool isUndo)
        {
            var handler = BoardChanging;

            if (handler != null)
            {
                Util.CallEvent(
                    () => handler(this, new BoardChangedEventArgs(move, isUndo)));
            }
        }
Exemple #13
0
        /// <summary>
        /// undo操作を実行します。
        /// </summary>
        private void DoUndo(BoardMove move)
        {
            if (move.IsSpecialMove)
            {
                // 何もしません。
            }
            else if (move.ActionType == ActionType.Drop)
            {
                // 駒打ちの場合は、その駒を駒台に戻します。
                this[move.DstSquare] = null;

                IncCapturedPieceCount(move.DropPieceType, move.BWType);
            }
            else
            {
                var movedPiece = this[move.DstSquare];

                // 駒を成った場合はそれを元に戻します。
                if (move.ActionType == ActionType.Promote)
                {
                    movedPiece.IsPromoted = false;
                }

                // 駒を取った場合は、その駒を元に戻します。
                if (move.TookPiece != null)
                {
                    this[move.DstSquare] = new BoardPiece(
                        move.TookPiece.Clone(),
                        move.BWType.Flip());

                    // 駒を取ったはずなので、その分を駒台から減らします。
                    DecCapturedPieceCount(
                        move.TookPiece.PieceType,
                        move.BWType);
                }
                else
                {
                    this[move.DstSquare] = null;
                }

                this[move.SrcSquare] = movedPiece;
            }

            if (!move.IsSpecialMove)
            {
                Turn            = Turn.Flip();
                PrevMovedSquare = (
                    this.moveList.Any() ?
                    this.moveList.Last().DstSquare :
                    null);
            }
        }
Exemple #14
0
        /// <summary>
        /// 駒を動かすか、または駒が動かせるか調べます。
        /// </summary>
        private bool CheckAndMakeMove(BoardMove move, MoveFlags flags)
        {
            if (move == null || !move.Validate())
            {
                throw new ArgumentNullException("move");
            }

            // 投了などの特殊な指し手がある場合はゲームが既に終了しているので
            // 指し手を進めることはできません。
            if (HasSpecialMove)
            {
                if (flags.HasFlag(MoveFlags.CheckOnly))
                {
                    // CheckOnlyの場合は、ここで失敗させません。
                }
                else if (flags.HasFlag(MoveFlags.AutoRemoveSpecialMove))
                {
                    // 特殊な指し手を取り除きます。
                    RemoveSpecialMove();
                }
                else
                {
                    return(false);
                }
            }

            using (LazyLock())
            {
                // 手番があわなければ失敗とします。
                if (EnumEx.HasFlag(flags, MoveFlags.CheckTurn))
                {
                    if (this.turn == BWType.None || this.turn != move.BWType)
                    {
                        return(false);
                    }
                }

                if (move.IsSpecialMove)
                {
                    return(CheckAndMakeSpecialMove(move, flags));
                }
                else if (move.ActionType == ActionType.Drop)
                {
                    return(CheckAndMakeDrop(move, flags));
                }
                else
                {
                    return(CheckAndMakeMoveOnly(move, flags));
                }
            }
        }
Exemple #15
0
        /// <summary>
        /// 文字列から得られた指し手から、移動前の情報も含むような
        /// 指し手情報を取得します。
        /// </summary>
        public static BoardMove ConvertMove(this Board board, Move move,
                                            BWType bwType,
                                            bool multipleIsNull = false)
        {
            if (board == null)
            {
                throw new ArgumentNullException("board");
            }

            if (move == null)
            {
                return(null);
            }

            if (move.SameAsOld && board.PrevMovedSquare == null)
            {
                return(null);
            }

            if (move.IsSpecialMove)
            {
                return(BoardMove.CreateSpecialMove(
                           bwType, move.SpecialMoveType));
            }

            // 移動後の位置を取得します。
            // 同○○なら前回の位置を使います。
            var dstSquare = move.DstSquare;

            if (move.SameAsOld)
            {
                move           = move.Clone();
                move.DstSquare = board.PrevMovedSquare;

                dstSquare = board.PrevMovedSquare;
            }

            var boardMoveList = board.ListupMoves(
                move.Piece, bwType, dstSquare)
                                .ToList();

            // 複数の指し手の中から適切な一つを選びます。
            var boardMove = FilterBoardMove(boardMoveList, move, multipleIsNull);

            if (boardMove == null)
            {
                return(null);
            }

            return(boardMove);
        }
Exemple #16
0
        /// <summary>
        /// 局面の変更を通知します。
        /// </summary>
        private void NotifyBoardChanged(BoardMove move, bool isUndo)
        {
            var handler = BoardChanged;

            if (handler != null)
            {
                Util.CallEvent(
                    () => handler(this, new BoardChangedEventArgs(move, isUndo)));
            }

            this.RaisePropertyChanged("MoveCount");
            this.RaisePropertyChanged("CanUndo");
            this.RaisePropertyChanged("CanRedo");
        }
Exemple #17
0
        /// <summary>
        /// 指し手の種類で手をフィルターし、Moveに適切なRankMoveTypeを設定します。
        /// </summary>
        private static List <BoardMove> FilterAction(Move move,
                                                     BoardMove referenceMove,
                                                     List <BoardMove> boardMoveList)
        {
            var tmpMoveList = boardMoveList.Where(
                mv => mv.ActionType == referenceMove.ActionType)
                              .ToList();

            if (tmpMoveList.Count() != boardMoveList.Count())
            {
                move.ActionType = referenceMove.ActionType;
            }

            return(tmpMoveList);
        }
Exemple #18
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 = BoardMove.CreateMove(
                bwType, srcSquare, dstSquare, piece.Piece, false);

            // 成り駒でなければ、成る可能性があります。
            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);
        }
Exemple #19
0
        /// <summary>
        /// 駒打ちの動作が行えるか調べ、必要なら実行します。
        /// </summary>
        private bool CheckAndMakeDrop(BoardMove move, MoveFlags flags)
        {
            if (GetCapturedPieceCount(move.DropPieceType, move.BWType) <= 0)
            {
                return(false);
            }

            // 駒を打つ場所に駒があれば、当然失敗です。
            var piece = this[move.DstSquare];

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

            // 駒が置けるか確かめます。
            if (!CanDrop(move.BWType, move.DstSquare, move.DropPieceType))
            {
                return(false);
            }

            // 打ち歩詰のチェックを行います。
            if (move.DropPieceType == PieceType.Hu &&
                IsDropPawnMate(move.BWType, move.DstSquare))
            {
                return(false);
            }

            if (!EnumEx.HasFlag(flags, MoveFlags.CheckOnly))
            {
                // 駒を盤面に置き、持ち駒から駒を減らします。
                this[move.DstSquare] = new BoardPiece(
                    move.DropPieceType, false, move.BWType);

                DecCapturedPieceCount(move.DropPieceType, move.BWType);

                MoveDone(move);
            }

            return(true);
        }
Exemple #20
0
        /// <summary>
        /// 指し手をXX->YYの形式から、ZZ銀上などの形に変換します。
        /// </summary>
        /// <remarks>
        /// <paramref name="useSrcSquare"/>を真にすると、差し手の後に
        /// 古い位置の情報が付加されるようになります。(例: 32金(22))
        /// </remarks>
        public static Move ConvertMove(this Board board, BoardMove move,
                                       bool useSrcSquare)
        {
            if (board == null)
            {
                throw new ArgumentNullException("board");
            }

            if (move == null || !move.Validate())
            {
                throw new ArgumentNullException("move");
            }

            if (move.IsSpecialMove)
            {
                return(new Move
                {
                    BWType = move.BWType,
                    SpecialMoveType = move.SpecialMoveType,
                });
            }

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

            if (fromPiece == null)
            {
                return(null);
            }

            // 駒の種類と最終位置から、あり得る指し手をすべて検索します。
            var boardMoveList = board.ListupMoves(
                fromPiece, move.BWType, move.DstSquare)
                                .ToList();

            return(FilterMove(
                       board, boardMoveList, move, fromPiece, useSrcSquare));
        }
Exemple #21
0
        /// <summary>
        /// 駒の移動のみの動作を調べるか実際にそれを行います。
        /// </summary>
        private bool CheckAndMakeMoveOnly(BoardMove move, MoveFlags flags)
        {
            // 駒の移動元に自分の駒がなければダメ
            var srcPiece = this[move.SrcSquare];

            if (srcPiece == null || srcPiece.BWType != move.BWType)
            {
                return(false);
            }

            // 駒の移動先に自分の駒があったらダメ
            var dstPiece = this[move.DstSquare];

            if (dstPiece != null && dstPiece.BWType == move.BWType)
            {
                return(false);
            }

            // これはエラーだけど。。。w
            if (srcPiece.Piece != move.MovePiece)
            {
                return(false);
            }

            // 各駒が動ける位置に移動するかどうか確認します。
            if (!CanMovePiece(move))
            {
                return(false);
            }

            if (move.ActionType == ActionType.Promote)
            {
                // 成れない場合は帰ります。
                if (!CanPromote(move))
                {
                    return(false);
                }
            }
            else
            {
                // 成らないといけない場合は帰ります。
                if (IsPromoteForce(move))
                {
                    return(false);
                }
            }

            if (!EnumEx.HasFlag(flags, MoveFlags.CheckOnly))
            {
                var pieceType = srcPiece.PieceType;

                // 移動先に駒があれば、それを自分のものにします。
                if (dstPiece != null)
                {
                    IncCapturedPieceCount(dstPiece.PieceType, move.BWType);

                    // 取った駒を記憶しておきます。
                    move.TookPiece = dstPiece.Piece;
                }

                // 移動後の駒の成り/不成りを決定します。
                var promoted = (
                    srcPiece.IsPromoted ||
                    move.ActionType == ActionType.Promote);

                this[move.DstSquare] = new BoardPiece(
                    pieceType, promoted, move.BWType);

                // 移動前の位置からは駒をなくします。
                this[move.SrcSquare] = null;

                // 前回の指し手と位置が同じか調べます。
                move.HasSameSquareAsPrev = (move.DstSquare == PrevMovedSquare);

                MoveDone(move);
            }

            return(true);
        }
Exemple #22
0
        /// <summary>
        /// 左、右、直の判定をします。
        /// </summary>
        private static bool CheckRelPosType(BoardMove bm,
                                            Move referenceMove,
                                            List <BoardMove> boardMoveList)
        {
            if (bm.ActionType == ActionType.Drop)
            {
                return(false);
            }

            if (bm.MovePiece == Piece.Ryu || bm.MovePiece == Piece.Uma)
            {
                // 竜、馬の場合、「直」は使わずに「右左」のみを使用します。
                if (boardMoveList.Count() == 1)
                {
                    return(referenceMove.RelFileType == RelFileType.None);
                }
                else
                {
                    // 駒は二つしかないはずなので、相方に比べて自分が
                    // 左にあれば「左」、右にあれば「右」となっているか
                    // 判定します。
                    var other = (
                        ReferenceEquals(bm, boardMoveList[0])
                        ? boardMoveList[1]
                        : boardMoveList[0]);
                    var fileDif = bm.SrcSquare.File - other.SrcSquare.File;

                    switch (referenceMove.RelFileType)
                    {
                    case RelFileType.Left:
                        return(bm.BWType == BWType.Black
                                        ? (fileDif > 0)
                                        : (fileDif < 0));

                    case RelFileType.Right:
                        return(bm.BWType == BWType.Black
                                        ? (fileDif < 0)
                                        : (fileDif > 0));

                    case RelFileType.None:
                        return(fileDif == 0);
                    }
                }
            }
            else
            {
                var fileMove = bm.DstSquare.File - bm.SrcSquare.File;
                var rankMove = bm.DstSquare.Rank - bm.SrcSquare.Rank;

                switch (referenceMove.RelFileType)
                {
                case RelFileType.Left:
                    return(bm.BWType == BWType.Black
                                    ? (fileMove < 0)
                                    : (fileMove > 0));

                case RelFileType.Right:
                    return(bm.BWType == BWType.Black
                                    ? (fileMove > 0)
                                    : (fileMove < 0));

                case RelFileType.Straight:
                    return((bm.BWType == BWType.Black
                                    ? (rankMove < 0)
                                    : (rankMove > 0)) &&
                           (fileMove == 0));
                }
            }

            return(false);
        }
Exemple #23
0
        /// <summary>
        /// その指し手を実際に実行します。
        /// </summary>
        public bool DoMove(BoardMove move, MoveFlags flags = MoveFlags.DoMoveDefault)
        {
            flags &= ~MoveFlags.CheckOnly;

            return(CheckAndMakeMove(move, flags));
        }
Exemple #24
0
        /// <summary>
        /// 列で指し手をフィルターし、Moveに適切なRelPosTypeを設定します。
        /// </summary>
        private static List <BoardMove> FilterFile(Move move,
                                                   BoardMove referenceMove,
                                                   List <BoardMove> boardMoveList)
        {
            // 駒の移動前情報が必要です。
            var nextPos = referenceMove.DstSquare;
            var prevPos = referenceMove.SrcSquare;

            if (prevPos == null)
            {
                // 何もフィルターしません。
                return(boardMoveList);
            }

            if ((move.Piece == Piece.Ryu || move.Piece == Piece.Uma) &&
                boardMoveList.Count() == 2)
            {
                // 馬と竜の場合は'直'ではなく、右と左しか使いません。
                var other = (
                    referenceMove == boardMoveList[0] ?
                    boardMoveList[1] : boardMoveList[0]);

                // 動かす前の駒が相方に比べて右にあるか左にあるか調べます。
                // 先手の場合は筋が小さい方が右です。
                var relFile = prevPos.File - other.SrcSquare.File;
                relFile *= (referenceMove.BWType == BWType.White ? -1 : +1);

                if (relFile == 0)
                {
                    return(boardMoveList);
                }
                else if (relFile < 0)
                {
                    move.RelFileType = RelFileType.Right;
                }
                else
                {
                    move.RelFileType = RelFileType.Left;
                }

                return(new List <BoardMove> {
                    referenceMove
                });
            }
            else
            {
                // 黒から見ると正の場合は引く or 左へ移動(右)で
                // 負の場合は上がる or 右へ移動(左)です。
                var relFile = nextPos.File - prevPos.File;

                // 列の位置でフィルターします。
                var tmpMoveList = boardMoveList.Where(mv =>
                {
                    var rel = nextPos.File - mv.SrcSquare.File;
                    return(
                        relFile < 0 ? (rel < 0) :
                        relFile > 0 ? (rel > 0) :
                        (rel == 0));
                }).ToList();

                // 列情報でフィルターされた場合は、列の移動情報を付加します。
                if (tmpMoveList.Count() != boardMoveList.Count())
                {
                    var relFile2 = relFile * referenceMove.BWType.Sign();

                    if (relFile2 < 0)
                    {
                        move.RelFileType = RelFileType.Left;
                    }
                    else if (relFile2 > 0)
                    {
                        move.RelFileType = RelFileType.Right;
                    }
                    else
                    {
                        // 直の場合は、左右の動きはありません。
                        move.RankMoveType = RankMoveType.None;
                        move.RelFileType  = RelFileType.Straight;
                    }
                }

                return(tmpMoveList);
            }
        }
Exemple #25
0
 /// <summary>
 /// コンストラクタ
 /// </summary>
 public BoardChangedEventArgs(BoardMove move, bool isUndo)
 {
     Move   = move;
     IsUndo = isUndo;
 }
Exemple #26
0
        /// <summary>
        /// 実際に駒が動けるか確認します。
        /// </summary>
        private bool CanMovePiece(BoardMove move)
        {
            var relFile = move.DstSquare.File - move.SrcSquare.File;
            var relRank = move.DstSquare.Rank - move.SrcSquare.Rank;
            var piece   = move.MovePiece;

            if (piece.IsPromoted)
            {
                // 成り駒が指定の場所に動けるか調べます。
                switch (piece.PieceType)
                {
                case PieceType.Gyoku:
                    return(CanMoveWithTable(move.BWType, relFile, relRank, MoveTableGyoku));

                case PieceType.Hisya:
                    if (CanMoveWithTable(move.BWType, relFile, relRank, MoveTableGyoku))
                    {
                        return(true);
                    }
                    return(CanMoveHisya(move.SrcSquare, relFile, relRank));

                case PieceType.Kaku:
                    if (CanMoveWithTable(move.BWType, relFile, relRank, MoveTableGyoku))
                    {
                        return(true);
                    }
                    return(CanMoveKaku(move.SrcSquare, relFile, relRank));

                case PieceType.Kin:
                case PieceType.Gin:
                case PieceType.Kei:
                case PieceType.Kyo:
                case PieceType.Hu:
                    return(CanMoveWithTable(move.BWType, relFile, relRank, MoveTableKin));
                }
            }
            else
            {
                // 成り駒以外の駒が指定の場所に動けるか調べます。
                switch (piece.PieceType)
                {
                case PieceType.Gyoku:
                    return(CanMoveWithTable(move.BWType, relFile, relRank, MoveTableGyoku));

                case PieceType.Hisya:
                    return(CanMoveHisya(move.SrcSquare, relFile, relRank));

                case PieceType.Kaku:
                    return(CanMoveKaku(move.SrcSquare, relFile, relRank));

                case PieceType.Kin:
                    return(CanMoveWithTable(move.BWType, relFile, relRank, MoveTableKin));

                case PieceType.Gin:
                    return(CanMoveWithTable(move.BWType, relFile, relRank, MoveTableGin));

                case PieceType.Kei:
                    return(CanMoveWithTable(move.BWType, relFile, relRank, MoveTableKei));

                case PieceType.Kyo:
                    return(CanMoveKyo(move.BWType, move.SrcSquare, relFile, relRank));

                case PieceType.Hu:
                    return(CanMoveWithTable(move.BWType, relFile, relRank, MoveTableHu));
                }
            }

            return(false);
        }