Пример #1
0
        /// <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);
        }
        public CharacterCore Spawn()
        {
            switch (CharacterAsset)
            {
            case PlayerAsset asset:
                var id = asset.ID;
                if (PlayerIDOverride)
                {
                    asset.ID = OverrideID;
                }


                // var player = CharacterCore.Create<PlayerCore>(asset, transform);
                var player = _playerBuilder.Create(asset, transform);

                asset.ID = id;

                return(player);

            case EnemyAsset asset:
//					return CharacterCore.Create<EnemyCore>(asset, transform);
                return(_enemyBuilder.Create(asset, transform));

            default:
                return(null);
            }
        }
Пример #3
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;
        }
Пример #4
0
        /// <summary>
        /// [Worker Thread] : 検討モードに入る。
        /// GameModeのsetterから呼び出される。
        /// </summary>
        /// <param name="nextGameMode">次に遷移するGameMode</param>
        /// <returns>返し値としてfalseを返すとcancel動作</returns>
        private bool StartConsiderationWithEngine(GameModeEnum nextGameMode)
        {
            try
            {
                CanUserMove = true;

                // 検討モード用のプレイヤーセッティングを行う。

                // 検討用エンジン
                //var engineDefineFolderPath = "\\engine\\gpsfish"; // 開発テスト用

                var engineDefineFolderPath =
                    (nextGameMode == GameModeEnum.ConsiderationWithEngine)     ? TheApp.app.Config.ConsiderationEngineSetting.EngineDefineFolderPath :
                    (nextGameMode == GameModeEnum.ConsiderationWithMateEngine) ? TheApp.app.Config.MateEngineSetting.EngineDefineFolderPath :
                    null;

                var engineDefineEx = TheApp.app.EngineDefines.Find(x => x.FolderPath == engineDefineFolderPath);

                if (engineDefineEx == null)
                {
                    throw new Exception("検討用エンジンが存在しません。\r\n" +
                                        "EngineDefineFolderPath = " + engineDefineFolderPath);
                }

                {
                    // 検討モードの名前はエンジン名から取得
                    // → ただし、棋譜を汚してはならないので棋譜の対局者名には反映しない。

                    var engineDefine = engineDefineEx.EngineDefine;

                    //var engineName = engineDefine.DisplayName;
                    //setting.PlayerSetting(Color.BLACK).PlayerName = engineName;
                    //setting.PlayerSetting(Color.BLACK).IsCpu = true;

                    switch (nextGameMode)
                    {
                    // 検討用エンジン
                    case GameModeEnum.ConsiderationWithEngine:
                        Players[0 /*検討用のプレイヤー*/] = PlayerBuilder.Create(PlayerTypeEnum.UsiEngine);
                        break;

                    // 詰将棋エンジン
                    case GameModeEnum.ConsiderationWithMateEngine:
                        Players[0 /* 詰将棋用のプレイヤー */] = PlayerBuilder.Create(PlayerTypeEnum.UsiEngine);
                        break;
                    }
                }

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

                // 検討用エンジンの開始

                var usiEnginePlayer = Players[0] as UsiEnginePlayer;
                InitUsiEnginePlayer(Color.BLACK, usiEnginePlayer, engineDefineEx, 0, nextGameMode, false);

                // エンジンに与えるHashSize,Threadsの計算
                if (UsiEngineHashManager.CalcHashSize() != 0)
                {
                    // Hash足りなくてダイアログ出した時にキャンセルボタン押されとる
                    // すぐ下でcatchされるので心配いらない。
                    throw new Exception("");
                }

                // エンジンを開始させることが確定したので実際に子プロセスとして起動する。
                StartEngine(usiEnginePlayer, engineDefineEx);

                // 検討ウィンドウへの読み筋などのリダイレクトを設定
                InitEngineConsiderationInfo(nextGameMode);

                return(true);
            } catch (Exception ex)
            {
                if (!ex.Message.Empty())
                {
                    TheApp.app.MessageShow(ex.Message, MessageShowType.Error);
                }
                Disconnect();

                // 失敗。GameModeの状態遷移をcancelすべき。
                return(false);
            }
        }
Пример #5
0
        /// <summary>
        /// 対局開始のためにGameSettingの設定に従い、ゲームを初期化する。
        /// </summary>
        /// <param name="gameSetting"></param>
        private void GameStart(GameSetting gameSetting)
        {
            // エンジン検討中であるなら、まずそれを停止させる。(通常検討モードに移行する)
            // これは、GameModeへの代入によって自動的に処理がなされる。
            if (GameMode.IsConsiderationWithEngine())
            {
                GameMode = GameModeEnum.ConsiderationWithoutEngine;
            }

            // 持ち時間などの設定が必要なので、
            // GameStart()時点のGameSettingをこのクラスのpropertyとしてコピーしておく。
            GameSetting = gameSetting;

            var nextGameMode = GameModeEnum.InTheGame;

            // -- 連続対局の回数をセット

            var misc = gameSetting.MiscSettings;

            // CPU同士の時のみ連続対局が有効である。

            // ContinuousGameの初期化
            {
                continuousGame.SetPlayLimit(
                    gameSetting.PlayerSetting(Color.BLACK).IsCpu&&
                    gameSetting.PlayerSetting(Color.WHITE).IsCpu&&
                    misc.ContinuousGameEnable ? misc.ContinuousGame : 0
                    );

                // 連続対局時にはプレイヤー入れ替えなどで壊す可能性があるのでClone()して保存しておく。
                continuousGame.GameSetting = gameSetting.Clone();

                // 対局開始時の振り駒のアニメーションのため、こちらにコピーして使う。
                continuousGame.EnablePieceToss = gameSetting.MiscSettings.EnablePieceToss;

                // 振り駒をするのかのチェック
                CheckPieceToss(nextGameMode);
            }

            // 以下の初期化中に駒が動かされるの気持ち悪いのでユーザー操作を禁止しておく。
            CanUserMove  = false;
            Initializing = true;

            var config = TheApp.app.Config;

            // 音声:「よろしくお願いします。」
            TheApp.app.SoundManager.Stop(); // 再生中の読み上げをすべて停止
            if (config.ReadOutGreeting != 0)
            {
                TheApp.app.SoundManager.ReadOut(SoundEnum.Start);
            }

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

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

            // Players[]の生成が終わったので、必要ならば画面に「エンジン初期化中」の画像を描画する。
            UpdateEngineInitializing();

            foreach (var c in All.Colors())
            {
                // これ書くの2度目だが、まあ、しゃーない。
                var gamePlayer = gameSetting.PlayerSetting(c);
                var playerType = gamePlayer.IsHuman ? PlayerTypeEnum.Human : PlayerTypeEnum.UsiEngine;

                if (playerType == PlayerTypeEnum.UsiEngine)
                {
                    var engineDefineEx = TheApp.app.EngineDefines.Find(x => x.FolderPath == gamePlayer.EngineDefineFolderPath);
                    if (engineDefineEx == null)
                    {
                        TheApp.app.MessageShow("エンジンがありませんでした。" + gamePlayer.EngineDefineFolderPath, MessageShowType.Error);
                        return;
                    }
                    var usiEnginePlayer = Players[(int)c] as UsiEnginePlayer;
                    var ponder          = gamePlayer.Ponder;
                    InitUsiEnginePlayer(c, usiEnginePlayer, engineDefineEx, gamePlayer.SelectedEnginePreset, nextGameMode, ponder);
                }
            }

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

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

                kifuManager.Tree.ClearForward();

                // 分岐棋譜かも知れないので、現在のものを本譜の手順にする。
                kifuManager.Tree.MakeCurrentNodeMainBranch(); // View側の都合により選択行が移動してしまう可能性がある。

                // 連続対局が設定されているなら、現在の局面を棋譜文字列として保存しておく。
                if (continuousGame.IsContinuousGameSet())
                {
                    continuousGame.Kif = kifuManager.ToString(KifuFileType.KIF);
                }
            }
            else // if (gameSetting.Board.BoardTypeEnable)
            {
                kifuManager.Init();
                kifuManager.InitBoard(gameSetting.BoardSetting.BoardType);
            }

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

            // エンジンに与えるHashSize,Threadsの計算
            var firstOfContinuousGame = continuousGame.PlayCount == 0; // 連続対局の初回局である

            if (UsiEngineHashManager.CalcHashSize(firstOfContinuousGame) != 0)
            {
                // Hash足りなくてダイアログ出した時にキャンセルボタン押されとる
                Disconnect();

                // ゲームが終局したことを通知するために音声があったほうがよさげ。
                TheApp.app.SoundManager.ReadOut(SoundEnum.End);

                return;
            }

            // エンジンを開始させることが確定したので実際に子プロセスとして起動する。
            // 1) このタイミングにしないと、Hashが足りなくてユーザーがキャンセルする可能性があって、
            // それまでにエンジンがタイムアウトになりかねない。
            // 2) エンジンを起動させてから、Hashの計算をするのでは、エンジンを起動させる時間が無駄である。
            foreach (var c in All.Colors())
            {
                // これ書くの3度目だが、まあしゃーない…。
                var gamePlayer = gameSetting.PlayerSetting(c);
                var playerType = gamePlayer.IsHuman ? PlayerTypeEnum.Human : PlayerTypeEnum.UsiEngine;

                if (playerType == PlayerTypeEnum.UsiEngine)
                {
                    var engineDefineEx  = TheApp.app.EngineDefines.Find(x => x.FolderPath == gamePlayer.EngineDefineFolderPath);
                    var usiEnginePlayer = Players[(int)c] as UsiEnginePlayer;

                    // これで子プロセスとして起動する。
                    StartEngine(usiEnginePlayer, engineDefineEx);
                }
            }

            // Restart処理との共通部分
            GameStartInCommon(nextGameMode);

            // 新規対局で手番が変わった。
            //NotifyTurnChanged();
            // → エンジンの初期化が現時点では終わっていない。
            //  ゆえに、UpdateInitializing()のなかで初期化が終わったタイミングでNotifyTurnChanged()を呼ぶ。
            // それまではTimeUpの処理をしてはならない。
        }
Пример #6
0
        /// <summary>
        /// 対局開始のためにGameSettingの設定に従い、ゲームを初期化する。
        /// </summary>
        /// <param name="gameSetting"></param>
        private void GameStart(GameSetting gameSetting)
        {
            // 以下の初期化中に駒が動かされるの気持ち悪いのでユーザー操作を禁止しておく。
            CanUserMove  = false;
            Initializing = true;
            var nextGameMode = GameModeEnum.InTheGame;

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

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

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

                if (playerType == PlayerTypeEnum.UsiEngine)
                {
                    var engineDefineEx = TheApp.app.EngineDefines.Find(x => x.FolderPath == gamePlayer.EngineDefineFolderPath);
                    if (engineDefineEx == null)
                    {
                        TheApp.app.MessageShow("エンジンがありませんでした。" + gamePlayer.EngineDefineFolderPath, MessageShowType.Error);
                        return;
                    }
                    var usiEnginePlayer = Players[(int)c] as UsiEnginePlayer;
                    var ponder          = gamePlayer.Ponder;
                    InitUsiEnginePlayer(c, usiEnginePlayer, engineDefineEx, gamePlayer.SelectedEnginePreset, nextGameMode, ponder);
                }
            }

            // 局面の設定
            kifuManager.EnableKifuList = true;
            if (gameSetting.BoardSetting.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.BoardSetting.BoardType);
            }

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

            // エンジンに与えるHashSize,Threadsの計算
            if (UsiEngineHashManager.CalcHashSize() != 0)
            {
                // Hash足りなくてダイアログ出した時にキャンセルボタン押されとる
                Disconnect();

                // ゲームが終局したことを通知するために音声があったほうがよさげ。
                TheApp.app.soundManager.ReadOut(SoundEnum.End);

                return;
            }

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

            // 対局者氏名の設定
            // 人間の時のみ有効。エンジンの時は、エンジン設定などから取得することにする。
            foreach (var c in All.Colors())
            {
                var    player = Player(c);
                string name;
                switch (player.PlayerType)
                {
                case PlayerTypeEnum.Human:
                    name = gameSetting.PlayerSetting(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();
                timeSettingStrings[(int)c] = pc.KifuTimeSetting.ToShortString();
            }

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

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

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

            // プレイヤー情報などを検討ダイアログに反映させる。
            InitEngineConsiderationInfo(nextGameMode);

            // 検討モードならそれを停止させる必要があるが、それはGameModeのsetterがやってくれる。
            GameMode = nextGameMode;
        }
Пример #7
0
        /// <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;
        }
Пример #8
0
        /// <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;
        }
Пример #9
0
        /// <summary>
        /// 対局開始のためにGameSettingの設定に従い、ゲームを初期化する。
        /// </summary>
        /// <param name="gameSetting"></param>
        private void GameStart(GameSetting gameSetting)
        {
            // -- 連続対局の回数をセット

            var misc = gameSetting.MiscSettings;

            // CPU同士の時のみ連続対局が有効である。
            ContinuousGame =
                gameSetting.PlayerSetting(Color.BLACK).IsCpu&&
                gameSetting.PlayerSetting(Color.WHITE).IsCpu&&
                misc.ContinuousGameEnable ? misc.ContinuousGame : 0;
            ContinuousGameCount = 0;

            // 以下の初期化中に駒が動かされるの気持ち悪いのでユーザー操作を禁止しておく。
            CanUserMove  = false;
            Initializing = true;

            var nextGameMode = GameModeEnum.InTheGame;

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

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

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

            // Players[]の生成が終わったので、必要ならば画面に「エンジン初期化中」の画像を描画する。
            UpdateInitializing();

            foreach (var c in All.Colors())
            {
                // これ書くの2度目だが、まあ、しゃーない。
                var gamePlayer = gameSetting.PlayerSetting(c);
                var playerType = gamePlayer.IsHuman ? PlayerTypeEnum.Human : PlayerTypeEnum.UsiEngine;

                if (playerType == PlayerTypeEnum.UsiEngine)
                {
                    var engineDefineEx = TheApp.app.EngineDefines.Find(x => x.FolderPath == gamePlayer.EngineDefineFolderPath);
                    if (engineDefineEx == null)
                    {
                        TheApp.app.MessageShow("エンジンがありませんでした。" + gamePlayer.EngineDefineFolderPath, MessageShowType.Error);
                        return;
                    }
                    var usiEnginePlayer = Players[(int)c] as UsiEnginePlayer;
                    var ponder          = gamePlayer.Ponder;
                    InitUsiEnginePlayer(c, usiEnginePlayer, engineDefineEx, gamePlayer.SelectedEnginePreset, nextGameMode, ponder);
                }
            }

            // 局面の設定
            kifuManager.EnableKifuList = true;
            if (gameSetting.BoardSetting.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.BoardSetting.BoardType);
            }

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

            // エンジンに与えるHashSize,Threadsの計算
            var firstOfContinuousGame = ContinuousGameCount == 0; // 連続対局の初回局である

            if (UsiEngineHashManager.CalcHashSize(firstOfContinuousGame) != 0)
            {
                // Hash足りなくてダイアログ出した時にキャンセルボタン押されとる
                Disconnect();

                // ゲームが終局したことを通知するために音声があったほうがよさげ。
                TheApp.app.SoundManager.ReadOut(SoundEnum.End);

                return;
            }

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

            // Restart処理との共通部分
            GameStartInCommon(nextGameMode);
        }