/// <summary>
        /// [Worker Thread] : 検討モードに入る。
        /// GameModeのsetterから呼び出される。
        /// </summary>
        private void StartConsideration()
        {
            CanUserMove = true;

            // 検討モード用のプレイヤーセッティングを行う。
            {
                var setting = new GameSetting();

                switch (GameMode)
                {
                // 検討用エンジン
                case GameModeEnum.ConsiderationWithEngine:
                    setting.Player(Color.BLACK).PlayerName = "検討エンジン";
                    setting.Player(Color.BLACK).IsCpu      = true;
                    Players[0 /*検討用のプレイヤー*/] = PlayerBuilder.Create(PlayerTypeEnum.UsiEngine);
                    break;

                // 詰将棋エンジン
                case GameModeEnum.ConsiderationWithMateEngine:
                    setting.Player(Color.BLACK).PlayerName = "詰将棋エンジン";
                    setting.Player(Color.BLACK).IsCpu      = true;
                    Players[0 /* 詰将棋用のプレイヤー */]            = PlayerBuilder.Create(PlayerTypeEnum.UsiEngine);
                    break;
                }
                GameSetting = setting;
            }

            // 局面の設定
            kifuManager.EnableKifuList = false;

            // 検討ウィンドウへの読み筋などのリダイレクトを設定
            InitEngineConsiderationInfo(GameMode);
        }
Beispiel #2
0
        /// <summary>
        /// 対局開始のためにGameSettingの設定に従い、ゲームを初期化する。
        /// </summary>
        /// <param name="gameSetting"></param>
        private void GameStart(GameSetting gameSetting)
        {
            // 初期化中である。
            Initializing = true;

            // プレイヤーの生成
            foreach (var c in All.Colors())
            {
                var playerType = gameSetting.Player(c).IsHuman ? PlayerTypeEnum.Human : PlayerTypeEnum.UsiEngine;
                Players[(int)c] = PlayerBuilder.Create(playerType);
            }

            // 局面の設定
            if (gameSetting.Board.BoardTypeCurrent)
            {
                // 現在の局面からなので、いま以降の局面を削除する。
                kifuManager.Tree.ClearForward();
            }
            else // if (gameSetting.Board.BordTypeEnable)
            {
                kifuManager.Init();
                kifuManager.InitBoard(gameSetting.Board.BoardType);
            }

            // 対局者氏名の設定
            // 人間の時のみ有効。エンジンの時は、エンジン設定などから取得することにする。(TODO:あとで考える)
            foreach (var c in All.Colors())
            {
                var    player = Player(c);
                string name;
                switch (player.PlayerType)
                {
                case PlayerTypeEnum.Human:
                    name = gameSetting.Player(c).PlayerName;
                    break;

                default:
                    name = c.Pretty();
                    break;
                }

                kifuManager.SetPlayerName(c, name);
            }

            // 持ち時間などの設定が必要なので、コピーしておく。
            GameSetting = gameSetting;

            // 消費時間計算用
            foreach (var c in All.Colors())
            {
                var pc = PlayerConsumption(c);
                pc.TimeSetting = GameSetting.TimeSettings.Player(c);
                pc.GameStart();
                SetRestTimeString(c, pc.DisplayShortString());
            }

            InTheGame = true;
        }
        /// <summary>
        /// 対局開始のためにGameSettingの設定に従い、ゲームを初期化する。
        /// </summary>
        /// <param name="gameSetting"></param>
        private void GameStart(GameSetting gameSetting)
        {
            // 以下の初期化中に駒が動かされるの気持ち悪いのでユーザー操作を禁止しておく。
            CanUserMove      = false;
            lastInitializing = true;

            // 音声:「よろしくお願いします。」
            TheApp.app.soundManager.Stop(); // 再生中の読み上げをすべて停止
            TheApp.app.soundManager.ReadOut(SoundEnum.Start);

            // 初回の指し手で、「先手」「後手」と読み上げるためのフラグ
            sengo_read_out = new bool[2] {
                false, false
            };

            // プレイヤーの生成
            foreach (var c in All.Colors())
            {
                var playerType = gameSetting.Player(c).IsHuman ? PlayerTypeEnum.Human : PlayerTypeEnum.UsiEngine;
                Players[(int)c] = PlayerBuilder.Create(playerType);
            }

            // 局面の設定
            kifuManager.EnableKifuList = true;
            if (gameSetting.Board.BoardTypeCurrent)
            {
                // 現在の局面からなので、いま以降の局面を削除する。
                // ただし、いまの局面と棋譜ウィンドウとが同期しているとは限らない。
                // まず現在局面以降の棋譜を削除しなくてはならない。

                // 元nodeが、special moveであるなら、それを削除しておく。
                if (kifuManager.Tree.IsSpecialNode())
                {
                    kifuManager.Tree.UndoMove();
                }

                kifuManager.Tree.ClearForward();

                // 分岐棋譜かも知れないので、現在のものを本譜の手順にする。
                kifuManager.Tree.MakeCurrentNodeMainBranch();
            }
            else // if (gameSetting.Board.BoardTypeEnable)
            {
                kifuManager.Init();
                kifuManager.InitBoard(gameSetting.Board.BoardType);
            }

            // 本譜の手順に変更したので現在局面と棋譜ウィンドウのカーソルとを同期させておく。
            UpdateKifuSelectedIndex();

            // 現在の時間設定を、KifuManager.Treeに反映させておく(棋譜保存時にこれが書き出される)
            kifuManager.Tree.KifuTimeSettings = gameSetting.KifuTimeSettings;

            // 対局者氏名の設定
            // 人間の時のみ有効。エンジンの時は、エンジン設定などから取得することにする。(TODO:あとで考える)
            foreach (var c in All.Colors())
            {
                var    player = Player(c);
                string name;
                switch (player.PlayerType)
                {
                case PlayerTypeEnum.Human:
                    name = gameSetting.Player(c).PlayerName;
                    break;

                default:
                    name = c.Pretty();
                    break;
                }

                kifuManager.KifuHeader.SetPlayerName(c, name);
            }

            // 持ち時間などの設定が必要なので、コピーしておく。
            GameSetting = gameSetting;

            // 消費時間計算用
            foreach (var c in All.Colors())
            {
                var pc = PlayTimer(c);
                pc.KifuTimeSetting = GameSetting.KifuTimeSettings.Player(c);
                pc.GameStart();
            }

            // rootの持ち時間設定をここに反映させておかないと待ったでrootまで持ち時間が戻せない。
            // 途中の局面からだとここではなく、現局面のところに書き出す必要がある。
            kifuManager.Tree.SetKifuMoveTimes(PlayTimers.GetKifuMoveTimes());

            // コンピュータ vs 人間である場合、人間側を手前にしてやる。
            // 人間 vs 人間の場合も最初の手番側を手前にしてやる。
            var stm = kifuManager.Position.sideToMove;

            // 1. 手番側が人間である場合(非手番側が人間 or CPU)
            if (gameSetting.Player(stm).IsHuman)
            {
                BoardReverse = (stm == Color.WHITE);
            }
            // 2. 手番側がCPUで、非手番側が人間である場合。
            else if (gameSetting.Player(stm).IsCpu&& gameSetting.Player(stm.Not()).IsHuman)
            {
                BoardReverse = (stm == Color.BLACK);
            }

            // プレイヤー情報などを検討ダイアログに反映させる。
            var nextGameMode = GameModeEnum.InTheGame;

            InitEngineConsiderationInfo(nextGameMode);

            // 検討モードならそれを停止させる必要があるが、それはGameModeのsetterがやってくれる。
            GameMode = nextGameMode;
        }
        /// <summary>
        /// プレイヤー情報を検討ダイアログに反映させる。
        /// </summary>
        private void InitEngineConsiderationInfo(GameModeEnum nextGameMode)
        {
            // CPUの数をNumberOfEngineに反映。
            int num = 0;

            foreach (var c in All.Colors())
            {
                if (GameSetting.Player(c).IsCpu)
                {
                    ++num;
                }
            }
            NumberOfEngine = num;

            // エンジン数が確定したので、検討ウィンドウにNumberOfInstanceメッセージを送信してやる。
            ThinkReport = new UsiThinkReportMessage()
            {
                type   = UsiEngineReportMessageType.NumberOfInstance,
                number = NumberOfEngine,
            };
            ThinkReport = new UsiThinkReportMessage()
            {
                type = UsiEngineReportMessageType.SetGameMode,
                data = nextGameMode
            };

            // 各エンジンの情報を検討ウィンドウにリダイレクトするようにハンドラを設定
            num = 0;
            foreach (var c in All.Colors())
            {
                if (GameSetting.Player(c).IsCpu)
                {
                    var num_ = num; // copy for capturing

                    // 検討モードなら、名前は..
                    var name =
                        (nextGameMode == GameModeEnum.ConsiderationWithEngine) ? "検討用エンジン" :
                        (nextGameMode == GameModeEnum.ConsiderationWithMateEngine) ? "詰将棋エンジン" :
                        DisplayName(c);

                    ThinkReport = new UsiThinkReportMessage()
                    {
                        type   = UsiEngineReportMessageType.SetEngineName,
                        number = num_, // is captured
                        data   = name,
                    };

                    // UsiEngineのThinkReportプロパティを捕捉して、それを転送してやるためのハンドラをセットしておく。
                    var engine_player = Player(c) as UsiEnginePlayer;
                    engine_player.engine.AddPropertyChangedHandler("ThinkReport", (args) =>
                    {
                        //// 1) 読み筋の抑制条件その1
                        //// 人間対CPUで、メニューの「ウィンドウ」のところで表示するになっていない場合。
                        //var surpress1 = NumberOfEngine == 1 && !TheApp.app.config.EngineConsiderationWindowEnableWhenVsHuman;

                        if (ThinkReportEnable
                            /* && !(surpress1) */)
                        {
                            var report = args.value as UsiThinkReport;

                            // このクラスのpropertyのsetterを呼び出してメッセージを移譲してやる。
                            ThinkReport = new UsiThinkReportMessage()
                            {
                                type   = UsiEngineReportMessageType.UsiThinkReport,
                                number = num_, // is captrued
                                data   = report,
                            };
                        }
                    });

                    num++;
                }
            }
        }
        /// <summary>
        /// 対局開始のためにGameSettingの設定に従い、ゲームを初期化する。
        /// </summary>
        /// <param name="gameSetting"></param>
        private void GameStart(GameSetting gameSetting)
        {
            // 音声:「よろしくお願いします。」
            TheApp.app.soundManager.Stop(); // 再生中の読み上げをすべて停止
            TheApp.app.soundManager.ReadOut(SoundEnum.Start);

            // 初期化中である。
            Initializing = true;

            // 初回の指し手で、「先手」「後手」と読み上げるためのフラグ
            sengo_read_out = new bool[2] {
                false, false
            };

            // プレイヤーの生成
            foreach (var c in All.Colors())
            {
                var playerType = gameSetting.Player(c).IsHuman ? PlayerTypeEnum.Human : PlayerTypeEnum.UsiEngine;
                Players[(int)c] = PlayerBuilder.Create(playerType);
            }

            // 局面の設定
            kifuManager.EnableKifuList = true;
            if (gameSetting.Board.BoardTypeCurrent)
            {
                // 現在の局面からなので、いま以降の局面を削除する。
                // ただし、いまの局面と棋譜ウィンドウとが同期しているとは限らない。
                // まず現在局面以降の棋譜を削除しなくてはならない。

                // 元nodeが、special moveであるなら、それを削除しておく。
                if (kifuManager.Tree.IsSpecialNode())
                {
                    kifuManager.Tree.UndoMove();
                }

                kifuManager.Tree.ClearForward();

                // 分岐棋譜かも知れないので、現在のものを本譜の手順にする。
                kifuManager.Tree.MakeCurrentNodeMainBranch();
            }
            else // if (gameSetting.Board.BordTypeEnable)
            {
                kifuManager.Init();
                kifuManager.InitBoard(gameSetting.Board.BoardType);
            }

            // 本譜の手順に変更したので現在局面と棋譜ウィンドウのカーソルとを同期させておく。
            UpdateKifuSelectedIndex();

            // 現在の時間設定を、KifuManager.Treeに反映させておく(棋譜保存時にこれが書き出される)
            kifuManager.Tree.KifuTimeSettings = gameSetting.KifuTimeSettings;

            // 対局者氏名の設定
            // 人間の時のみ有効。エンジンの時は、エンジン設定などから取得することにする。(TODO:あとで考える)
            foreach (var c in All.Colors())
            {
                var    player = Player(c);
                string name;
                switch (player.PlayerType)
                {
                case PlayerTypeEnum.Human:
                    name = gameSetting.Player(c).PlayerName;
                    break;

                default:
                    name = c.Pretty();
                    break;
                }

                kifuManager.KifuHeader.SetPlayerName(c, name);
            }

            // 持ち時間などの設定が必要なので、コピーしておく。
            GameSetting = gameSetting;

            // 消費時間計算用
            foreach (var c in All.Colors())
            {
                var pc = PlayTimer(c);
                pc.KifuTimeSetting = GameSetting.KifuTimeSettings.Player(c);
                pc.GameStart();
            }

            // rootの持ち時間設定をここに反映させておかないと待ったでrootまで持ち時間が戻せない。
            // 途中の局面からだとここではなく、現局面のところに書き出す必要がある。
            kifuManager.Tree.SetKifuMoveTimes(PlayTimers.GetKifuMoveTimes());

            // コンピュータ vs 人間である場合、人間側を手前にしてやる。
            foreach (var c in All.Colors())
            {
                if (gameSetting.Player(c).IsHuman&& gameSetting.Player(c.Not()).IsCpu)
                {
                    BoardReverse = (c == Color.WHITE);
                }
            }

            // 盤面編集中である可能性がある。リセットする。
            TheApp.app.config.InTheBoardEdit = false;

            InTheGame = true;
        }