Esempio n. 1
0
        /// <summary>
        /// 指し手を生成する
        ///
        /// from : 盤上の升のみでなく手駒もありうる
        /// to   : 盤上の升
        /// promote : 成るかどうか
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="promote"></param>
        /// <returns></returns>
        public static Move MakeMove(SquareHand from, SquareHand to, bool promote)
        {
            // ありえないはずだが…。
            if (!to.IsBoardPiece())
            {
                return(Move.NONE);
            }

            var to2 = (Square)to;

            if (from.IsHandPiece())
            {
                // 打ちと成りは共存できない
                if (promote)
                {
                    return(Move.NONE);
                }

                return(MakeMoveDrop(from.ToPiece(), to2));
            }
            else
            {
                var from2 = (Square)from;

                if (promote)
                {
                    return(MakeMovePromote(from2, to2));
                }
                else
                {
                    return(MakeMove(from2, to2));
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// [UI thread] : 盤面のsqの升(手駒・駒箱の駒も含む)が右クリックされた
        /// </summary>
        /// <param name="sq"></param>
        public void OnBoardRightClick(SquareHand sq)
        {
            if (gameServer.InTheBoardEdit)
            {
                // -- 盤面編集中

                var pos = gameServer.Position;

                // 盤上の駒はクリックされるごとに先手→先手成駒→後手→後手成駒のように駒の変化
                if (sq.IsBoardPiece())
                {
                    var pc = pos.PieceOn(sq);
                    var rp = pc.RawPieceType();

                    // 玉であっても手番変更は出来るのでNO_PIECE以外であれば処理対象。
                    if (pc != Piece.NO_PIECE)
                    {
                        Piece nextPc;
                        // 成っていない駒なら、成駒に。成っている駒なら相手番の成っていない駒に。
                        if (pc.CanPromote())
                        {
                            nextPc = pc.ToPromotePiece();
                        }
                        else
                        {
                            nextPc = Util.MakePiece(pc.PieceColor().Not() /*相手番の駒に*/, pc.RawPieceType());
                        }

                        BoardEditCommand((raw_pos) => { raw_pos.board[(int)sq] = nextPc; });
                    }
                }

                //Console.WriteLine(sq.Pretty());
            }
        }
Esempio n. 3
0
        public static Move MakeMove(SquareHand from, SquareHand to, bool promote)
        {
            if (!to.IsBoardPiece())
            {
                return(Move.NONE);
            }

            var to_ = (Square)to;

            if (from.IsHandPiece())
            {
                Piece pr = from.ToPiece();
                return(MakeMoveDrop(pr, to_));
            }
            else if (from.IsBoardPiece())
            {
                var from_ = (Square)from;
                if (promote)
                {
                    return(MakeMovePromote(from_, to_));
                }
                else
                {
                    return(MakeMove(from_, to_));
                }
            }

            return(Move.NONE);
        }
Esempio n. 4
0
        /// <summary>
        /// PickedToが適切であるか
        /// </summary>
        /// <param name="from"></param>
        /// <returns></returns>
        public bool IsOkPickedTo(SquareHand to)
        {
            if (!to.IsBoardPiece())
            {
                return(false);
            }

            Piece pc = Position.PieceOn(to);

            if (pc == Piece.NO_PIECE)
            {
                return(true);
            }

            return(pc.PieceColor() == Position.sideToMove.Not());
        }
Esempio n. 5
0
        public static Vector3 SquareToPosition(SquareHand sq)
        {
            if (sq.IsBoardPiece())
            {
                return(SquareToPosition((Square)sq));
            }

            int index = (int)sq.ToPiece();

            if (sq < SquareHand.HandWhite)
            {
                return(new Vector3(RookHandX + HAND_X[index], RookHandY, 0));
            }
            else
            {
                return(new Vector3(-RookHandX - HAND_X[index], -RookHandY, 0));
            }
        }
Esempio n. 6
0
        /// <summary>
        /// [UI thread] : 盤面のsqの升(手駒・駒箱の駒も含む)が右クリックされた
        /// </summary>
        /// <param name="sq"></param>
        public void OnBoardRightClick(SquareHand sq)
        {
            var config = TheApp.app.config;

            if (config.InTheBoardEdit)
            {
                // -- 盤面編集中

                var gameServer = ViewModel.ViewModel.gameServer;
                var pos        = gameServer.Position;

                // 盤上の駒はクリックされるごとに先手→先手成駒→後手→後手成駒のように駒の変化
                if (sq.IsBoardPiece())
                {
                    var pc = pos.PieceOn(sq);
                    var rp = pc.RawPieceType();
                    // 玉は裏返らないし、敵玉にもならない。(それが出来てしまうと先手玉が2枚の局面が作れてしまうため)
                    if (pc != Piece.NO_PIECE && rp != Piece.KING)
                    {
                        var RawBoard = new Piece[pos.RawBoard.Length];
                        pos.RawBoard.CopyTo(RawBoard, 0);

                        Piece nextPc;
                        // 成っていない駒なら、成駒に。成っている駒なら相手番の成っていない駒に。
                        if (pc.CanPromote())
                        {
                            nextPc = pc.ToPromotePiece();
                        }
                        else
                        {
                            nextPc = Util.MakePiece(pc.PieceColor().Not() /*相手番の駒に*/, pc.RawPieceType());
                        }
                        RawBoard[(int)sq] = nextPc;

                        var sfen = Position.SfenFromRawdata(RawBoard, pos.RawHands, pos.sideToMove, pos.gamePly);
                        gameServer.SetSfenCommand(sfen);
                    }
                }

                //Console.WriteLine(sq.Pretty());
            }
        }
Esempio n. 7
0
        /// <summary>
        /// [UI thread] : 盤面のsqの升(手駒も含む)がクリックされた
        /// </summary>
        /// <param name="sq"></param>
        public void OnBoardClick(SquareHand sq)
        {
            var pos   = gameServer.Position;
            var state = viewState;
            var pc    = pos.PieceOn(sq);

            //Console.WriteLine(sq.Pretty());

            if (gameServer.InTheBoardEdit)
            {
                // -- 盤面編集中

                switch (state.state)
                {
                case GameScreenControlViewStateEnum.Normal:
                {
                    // 盤面編集中はどの駒でも掴める
                    if (pc != Piece.NO_PIECE)
                    {
                        pick_up_for_edit(sq);
                    }
                    break;
                }

                case GameScreenControlViewStateEnum.PiecePickedUp:
                {
                    // 盤面編集中はどの駒でも掴める
                    state.picked_to = sq;
                    move_piece_for_edit(state.picked_from, state.picked_to);
                    break;
                }
                }
            }
            else
            {
                // -- 対局中、もしくは、対局終了後である。

                switch (state.state)
                {
                case GameScreenControlViewStateEnum.Normal:
                {
                    // 掴んだのが自分の駒であるか
                    if (pc != Piece.NO_PIECE && pc.PieceColor() == pos.sideToMove && !sq.IsPieceBoxPiece())
                    {
                        pick_up(sq);         // sqの駒を掴んで行き先の候補の升情報を更新する
                    }
                    break;
                }

                case GameScreenControlViewStateEnum.PiecePickedUp:
                {
                    // 次の4つのケースが考えられる
                    // 1.駒を掴んでいる状態なので移動先のクリック
                    // 2.自駒を再度掴んだ(掴んでいたのをキャンセルする)
                    // 3.別の自分の駒を掴んだ(掴み直し)
                    // 4.無縁の升をクリックした(掴んでいたのをキャンセルする)

                    // 1. 駒の移動

                    // いま掴んでいる駒の移動できる先であるのか。
                    var bb = state.picked_piece_legalmovesto;
                    if (sq.IsBoardPiece() && bb.IsSet((Square)sq))
                    {
                        state.picked_to = sq;
                        move_piece(state.picked_from, state.picked_to);
                    }
                    // 2. 掴んでいた駒の再クリック
                    else if (sq == state.picked_from)
                    {
                        StateReset();
                    }

                    // 3. 別の駒のクリック
                    else if (pc != Piece.NO_PIECE && pc.PieceColor() == pos.sideToMove && !sq.IsPieceBoxPiece())
                    {
                        pick_up(sq);
                    }

                    // 4. 掴む動作のキャンセル
                    else
                    {
                        StateReset();
                    }

                    break;
                }

                case GameScreenControlViewStateEnum.PromoteDialog:
                {
                    // PromoteDialogを出していたのであれば、
                    switch (state.promote_dialog_selection)
                    {
                    case PromoteDialogSelectionEnum.NO_SELECT:
                        break;             // 無視

                    case PromoteDialogSelectionEnum.CANCEL:
                        // キャンセルするので移動の駒の選択可能状態に戻してやる。
                        StateReset();
                        break;

                    // 成り・不成を選んでクリックしたのでそれに応じた移動を行う。
                    case PromoteDialogSelectionEnum.UNPROMOTE:
                    case PromoteDialogSelectionEnum.PROMOTE:
                        var m = Util.MakeMove(state.picked_from, state.picked_to,
                                              state.promote_dialog_selection == PromoteDialogSelectionEnum.PROMOTE);
                        DoMoveCommand(m);
                        break;
                    }

                    break;
                }
                }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// 駒の移動 盤面編集
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        public void move_piece_for_edit(SquareHand from, SquareHand to)
        {
            var pos = gameServer.Position;

            // 何にせよ、移動、もしくは交換をする。
            // → 交換をする実装、不評なので、将棋所・ShogiGUIに倣い、手駒に移動させる。

            var from_pc = pos.PieceOn(from);
            var from_pt = from_pc.PieceType();
            var from_pr = from_pc.RawPieceType();
            var to_pc   = pos.PieceOn(to);
            var to_pr   = to_pc.RawPieceType();

            // 移動元と移動先が同じなら何もする必要はない。
            if (from == to)
            {
                // このケースを除外しておかないと、toの駒を手駒に移動させる処理などで
                // from == toだと手駒が増えることになる。

                // しかし、駒を掴んでいる状態が変化するのでこのときだけ再描画は必要。
                Dirty = true;
            }
            else if (to.IsBoardPiece())
            {
                if (from.IsBoardPiece())
                {
                    // -- 盤上と盤上の駒

#if false // 2駒交換する実装 → 不評なので手駒に移動させることに変更。
                    // fromとtoの升の駒を交換する。
                    // fromに駒があることは確定している。toに駒があろうがなかろうが良い。
                    BoardEditCommand(raw =>
                    {
                        raw.board[(int)from] = to_pc;
                        raw.board[(int)to]   = from_pc;
                    });
#endif

#if true // toのほうが手駒に移動する実装
                    BoardEditCommand(raw =>
                    {
                        raw.board[(int)from] = Piece.NO_PIECE;
                        raw.board[(int)to]   = from_pc;
                        if (to_pr != Piece.NO_PIECE && to_pr != Piece.KING)
                        {
                            // 移動元の駒のcolorの手駒に移動させる。玉は、(欠落するので)勝手に駒箱に移動する。
                            raw.hands[(int)from_pc.PieceColor()].Add(to_pr);
                        }
                    });
#endif
                }
                else if (from.IsHandPiece())
                {
                    // -- 手駒を盤面に

                    BoardEditCommand(raw =>
                    {
#if false // 駒箱に移動する実装 → 不評なので手駒になるように変更
                        raw.hands[(int)from.PieceColor()].Sub(from_pt);
                        raw.board[(int)to] = from_pc;
                        // このtoの位置にもし駒があったとしたら、それは駒箱に移動する。
                        // (その駒が欠落するので..)
#endif

#if true // toのほうが手駒に移動する実装
                        raw.hands[(int)from.PieceColor()].Sub(from_pt);
                        raw.board[(int)to] = from_pc;

                        if (to_pr != Piece.NO_PIECE && to_pr != Piece.KING)
                        {
                            // 移動元の駒のcolorの手駒に移動させる。玉は、(欠落するので)勝手に駒箱に移動する。
                            raw.hands[(int)from.PieceColor()].Add(to_pr);
                        }
#endif
                    });
                }
                else if (from.IsPieceBoxPiece())
                {
                    // -- 駒箱の駒を盤面に
                    // toにあった駒は駒箱に戻ってくるが、これは仕方がない。

                    BoardEditCommand(raw => raw.board[(int)to] = from_pc);
                }
            }
            else if (to.IsHandPiece())
            {
                if (from.IsBoardPiece())
                {
                    // -- 盤上の駒を手駒に移動させる。

                    // 手駒に出来る駒種でなければキャンセル
                    if (from_pt == Piece.KING)
                    {
                        return;
                    }

                    BoardEditCommand(raw =>
                    {
                        raw.board[(int)from] = Piece.NO_PIECE;
                        raw.hands[(int)to.PieceColor()].Add(from_pr);
                    });
                }
                else if (from.IsHandPiece())
                {
                    // -- 手駒を手駒に。手番が違うならこれは合法。

                    if (from.PieceColor() != to.PieceColor())
                    {
                        BoardEditCommand(raw =>
                        {
                            // 同種の駒が駒台から駒台に移動するので、to_prは関係ない。
                            raw.hands[(int)from.PieceColor()].Sub(from_pr);
                            raw.hands[(int)to.PieceColor()].Add(from_pr);
                        });
                    }
                    else
                    {
                        // 手駒を同じ駒台に移動させることは出来ないし、
                        // 選び直しているのでは?

                        if (to_pr != Piece.NO_PIECE)
                        {
                            pick_up_for_edit(to);
                            return;
                        }
                    }
                }
                else if (from.IsPieceBoxPiece())
                {
                    // -- 駒箱の駒を手駒に

                    // 玉は移動手駒に出来ない
                    if (from_pt != Piece.KING)
                    {
                        BoardEditCommand(raw => raw.hands[(int)to.PieceColor()].Add(from_pr));
                    }
                }
            }
            else if (to.IsPieceBoxPiece())
            {
                if (from.IsBoardPiece())
                {
                    // -- 盤上の駒を駒箱に
                    BoardEditCommand(raw => raw.board[(int)from] = Piece.NO_PIECE);
                }
                else if (from.IsHandPiece())
                {
                    // -- 駒台の駒を駒箱に

                    BoardEditCommand(raw => raw.hands[(int)from.PieceColor()].Sub(from_pr));
                }
                else if (from.IsPieceBoxPiece())
                {
                    // 駒箱の駒を移動させることは出来ないし、
                    // 選び直しているのでは?

                    if (to_pr != Piece.NO_PIECE)
                    {
                        pick_up_for_edit(to);
                        return;
                    }
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// sqの描画する場所を得る。
        /// reverse : 盤面を180度回転するのかのフラグ
        /// </summary>
        /// <param name="sq"></param>
        /// <param name="reverse"></param>
        /// <returns></returns>
        private Point PieceLocation(SquareHand sq, bool reverse)
        {
            Point dest;

            if (sq.IsBoardPiece())
            {
                // -- 盤上の升

                Square sq2 = reverse ? ((Square)sq).Inv() : (Square)sq;
                int    f   = 8 - (int)sq2.ToFile();
                int    r   = (int)sq2.ToRank();

                dest = new Point(board_location.X + piece_img_size.Width * f, board_location.Y + piece_img_size.Height * r);
            }
            else if (sq.IsHandPiece())
            {
                // -- 手駒

                var color = sq.PieceColor();
                if (reverse)
                {
                    color = color.Not();
                }

                var v = PieceTableVersion;

                var pc = sq.ToPiece();

                if (color == ShogiCore.Color.BLACK)
                {
                    // Point型同士の加算は定義されていないので、第二項をSize型にcastしている。
                    dest = hand_table_pos[v, (int)color] + (Size)hand_piece_pos[v, (int)pc - 1];
                }
                else
                {
                    // 180度回転させた位置を求める
                    // 後手も駒の枚数は右肩に描画するのでそれに合わせて左右のmarginを調整する。
                    dest = new Point(
                        hand_table_pos[v, (int)color].X + (hand_table_size[v].Width - hand_piece_pos[v, (int)pc - 1].X - piece_img_size.Width - 10),
                        hand_table_pos[v, (int)color].Y + (hand_table_size[v].Height - hand_piece_pos[v, (int)pc - 1].Y - piece_img_size.Height + 0)
                        );
                }
            }
            else
            {
                // -- 駒箱の駒

                // 並び替える
                // pc : 歩=0,香=1,桂=2,銀=3,金=4,角=5,飛=6,玉=7にする。
                var pc = (int)sq.ToPiece() - 1;
                if (pc == 6)
                {
                    pc = 4;
                }
                else if (pc == 4 || pc == 5)
                {
                    ++pc;
                }

                if (PieceTableVersion == 0)
                {
                    // 駒箱の1段目に3枚、2段目に2枚、3段目に3枚表示する。

                    // 5を欠番にして2段目を2枚にする。
                    if (pc >= 5)
                    {
                        ++pc;
                    }

                    int file = pc % 3;
                    int rank = pc / 3;

                    int x = (int)(file * piece_img_size.Width * .8);
                    int y = (int)(rank * piece_img_size.Height * .88);

                    if (rank == 1)
                    {
                        x += (int)(piece_img_size.Width / 2 * 0.8);
                    }

                    dest = new Point(
                        hand_box_pos[0].X + x,
                        hand_box_pos[0].Y + y
                        );
                }
                else
                {
                    int file = pc % 2;
                    int rank = pc / 2;

                    int x = (int)(file * piece_img_size.Width * .5);
                    int y = (int)(rank * piece_img_size.Height * .65);

                    dest = new Point(
                        hand_box_pos[1].X + x,
                        hand_box_pos[1].Y + y
                        );
                }
            }

            return(dest);
        }
Esempio n. 10
0
        /// <summary>
        /// 駒の移動 盤面編集
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        public void move_piece_for_edit(SquareHand from, SquareHand to)
        {
            var pos = gameServer.Position;

            // 何にせよ、移動、もしくは交換をする。
            var from_pc = pos.PieceOn(from);
            var from_pt = from_pc.PieceType();
            var from_pr = from_pc.RawPieceType();
            var to_pc   = pos.PieceOn(to);
            var to_pr   = to_pc.RawPieceType();

            if (to.IsBoardPiece())
            {
                if (from.IsBoardPiece())
                {
                    // -- 盤上と盤上の駒

                    // fromとtoの升の駒を交換する。
                    // fromに駒があることは確定している。toに駒があろうがなかろうが良い。
                    BoardEditCommand(raw =>
                    {
                        raw.board[(int)from] = to_pc;
                        raw.board[(int)to]   = from_pc;
                    });
                }
                else if (from.IsHandPiece())
                {
                    // -- 手駒を盤面に

                    BoardEditCommand(raw =>
                    {
                        raw.hands[(int)from.PieceColor()].Sub(from_pt);
                        raw.board[(int)to] = from_pc;
                        // このtoの位置にもし駒があったとしたら、それは駒箱に移動する。
                        // (その駒が欠落するので..)
                    });
                }
                else if (from.IsPieceBoxPiece())
                {
                    // -- 駒箱の駒を盤面に

                    BoardEditCommand(raw => raw.board[(int)to] = from_pc);
                }
            }
            else if (to.IsHandPiece())
            {
                if (from.IsBoardPiece())
                {
                    // -- 盤上の駒を手駒に移動させる。

                    // 手駒に出来る駒種でなければキャンセル
                    if (from_pt == Piece.KING)
                    {
                        return;
                    }

                    BoardEditCommand(raw =>
                    {
                        raw.board[(int)from] = Piece.NO_PIECE;
                        raw.hands[(int)to.PieceColor()].Add(from_pr);
                    });
                }
                else if (from.IsHandPiece())
                {
                    // -- 手駒を手駒に。手番が違うならこれは合法。

                    if (from.PieceColor() != to.PieceColor())
                    {
                        BoardEditCommand(raw =>
                        {
                            // 同種の駒が駒台から駒台に移動するので、to_prは関係ない。
                            raw.hands[(int)from.PieceColor()].Sub(from_pr);
                            raw.hands[(int)to.PieceColor()].Add(from_pr);
                        });
                    }
                    else
                    {
                        // 手駒を同じ駒台に移動させることは出来ないし、
                        // 選び直しているのでは?

                        if (to_pr != Piece.NO_PIECE)
                        {
                            pick_up_for_edit(to);
                            return;
                        }
                    }
                }
                else if (from.IsPieceBoxPiece())
                {
                    // -- 駒箱の駒を手駒に

                    // 玉は移動手駒に出来ない
                    if (from_pt != Piece.KING)
                    {
                        BoardEditCommand(raw => raw.hands[(int)to.PieceColor()].Add(from_pr));
                    }
                }
            }
            else if (to.IsPieceBoxPiece())
            {
                if (from.IsBoardPiece())
                {
                    // -- 盤上の駒を駒箱に
                    BoardEditCommand(raw => raw.board[(int)from] = Piece.NO_PIECE);
                }
                else if (from.IsHandPiece())
                {
                    // -- 駒台の駒を駒箱に

                    BoardEditCommand(raw => raw.hands[(int)from.PieceColor()].Sub(from_pr));
                }
                else if (from.IsPieceBoxPiece())
                {
                    // 駒箱の駒を移動させることは出来ないし、
                    // 選び直しているのでは?

                    if (to_pr != Piece.NO_PIECE)
                    {
                        pick_up_for_edit(to);
                        return;
                    }
                }
            }

            StateReset();
        }