Exemplo n.º 1
0
        public JosekiMove AddMove(Move bestMove, Hyokati hyokati, int fukasa, int version)
        {
            JosekiMove josekiSs;

            if (!this.SsItems.ContainsKey(bestMove))
            {
                // 無ければ問答無用で追加☆(^▽^)
                josekiSs = new JosekiMove(bestMove, Move.Toryo, hyokati, fukasa, version, this);
                this.SsItems.Add(bestMove, josekiSs);
                this.Owner.Edited = true;
            }
            else
            {
                // 既存なら
                josekiSs = this.SsItems[bestMove];

                if (josekiSs.Version < version) // 新しいソフトの評価を優先☆
                {
                    josekiSs = new JosekiMove(bestMove, Move.Toryo, hyokati, fukasa, version, this);
                    this.SsItems[bestMove] = josekiSs;
                    this.Owner.Edited      = true;
                }
                // バージョンが同じなら
                else if (josekiSs.Fukasa < fukasa)// 深い探索の方を優先☆(^▽^)
                {
                    josekiSs = new JosekiMove(bestMove, Move.Toryo, hyokati, fukasa, version, this);
                    this.SsItems[bestMove] = josekiSs;
                    this.Owner.Edited      = true;
                }
                // 深さが同じなら
                // 無視☆
            }

            return(josekiSs);
        }
Exemplo n.º 2
0
 /// <summary>
 /// 反転できるものは反転するぜ☆(^▽^)
 /// </summary>
 /// <param name="ref_hyokati"></param>
 /// <returns></returns>
 public static void Hanten(ref Hyokati ref_hyokati)
 {
     if (Conv_Hyokati.InHyokatiOrTumeTesu(ref_hyokati))
     {
         ref_hyokati = (Hyokati)(-(int)ref_hyokati);
     }
 }
Exemplo n.º 3
0
        public static void Update(Hyokati hyokati, Option <Phase> optionalPhase, int teme)
        {
            var phaseIndex = OptionalPhase.IndexOf(optionalPhase);

            if (Conv_Hyokati.InTumeTesu(hyokati))
            {
                // 詰め手数が表示されているぜ☆

                if (Util_Taikyoku.PNNantedume_Teme[phaseIndex] == int.MaxValue)
                {
                    // 詰め手数が新たに表示されたようだぜ☆
                    Util_Taikyoku.PNNantedume_Teme[phaseIndex] = teme;
                }
                // 前から表示されていたのなら、そのままだぜ☆(^▽^)
            }
            else
            {
                // 詰め手数は、表示されていないぜ☆

                if (Util_Taikyoku.PNNantedume_Teme[phaseIndex] != int.MaxValue)
                {
                    // 詰め手数が消えたようだぜ☆
                    Util_Taikyoku.PNNantedume_Teme[phaseIndex] = int.MaxValue;
                }
                // もともと表示されていなかったのなら、そのままだぜ☆(^▽^)
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// 差分更新で使う☆(^▽^)駒取り☆
        /// </summary>
        public void Herasu(Option <Phase> optionalPhase, Koma km)
        {
            Hyokati henkaRyo = Conv_Hyokati.KomaHyokati[(int)km];

            this.Increase(optionalPhase, (Hyokati)(-(int)henkaRyo));
            this.Increase(Conv_Taikyokusya.Reverse(optionalPhase), henkaRyo);
        }
Exemplo n.º 5
0
        public static string ToContents(Hyokati hyokaSu)
        {
            StringBuilder hyoji = new StringBuilder();

            Setumei(hyokaSu, hyoji);
            return(hyoji.ToString());
        }
Exemplo n.º 6
0
        /// <summary>
        /// 差分更新で使う☆(^▽^)駒取り☆
        /// </summary>
        public void Hetta(Option <Phase> optionalPhase, MotiKoma mk)
        {
            Hyokati henkaRyo = Conv_MotiKoma.MotikomaHyokati[(int)mk];

            this.Increase(optionalPhase, (Hyokati)(-(int)henkaRyo));
            this.Increase(Conv_Taikyokusya.Reverse(optionalPhase), henkaRyo);
        }
Exemplo n.º 7
0
        public static void Update(Hyokati hyokaSu, Taikyokusya taikyokusya)
        {
            if (Conv_Tumesu.None != hyokaSu.tumeSu)
            {
                // 詰め手数が表示されているぜ☆

                if (Util_Taikyoku.nantedumeTeme_playerN[(int)taikyokusya] == int.MaxValue)
                {
                    // 詰め手数が新たに表示されたようだぜ☆
                    Util_Taikyoku.nantedumeTeme_playerN[(int)taikyokusya] = PureMemory.kifu_endTeme;
                }
                // 前から表示されていたのなら、そのままだぜ☆(^▽^)
            }
            else
            {
                // 詰め手数は、表示されていないぜ☆

                if (Util_Taikyoku.nantedumeTeme_playerN[(int)taikyokusya] != int.MaxValue)
                {
                    // 詰め手数が消えたようだぜ☆
                    Util_Taikyoku.nantedumeTeme_playerN[(int)taikyokusya] = int.MaxValue;
                }
                // もともと表示されていなかったのなら、そのままだぜ☆(^▽^)
            }
        }
Exemplo n.º 8
0
        public static void Assert_Sabun_Komawari(string message, Kyokumen.Sindanyo kys, StringBuilder syuturyoku)
        {
            KomawariHyokatiSabunItiran saikeisan = new KomawariHyokatiSabunItiran();

            saikeisan.Tukurinaosi(kys);
            Hyokati hyokati1 = kys.GetKomawari(OptionalPhase.Black);
            Hyokati hyokati2 = kys.GetKomawari(OptionalPhase.White);
            bool    safe     =
                hyokati1 == saikeisan.Get(OptionalPhase.Black)
                &&
                hyokati2 == saikeisan.Get(OptionalPhase.White)
            ;
            string msg = $@"{message}#河馬 診断 駒割り評価値
P1差分  =[{hyokati1}]
  再計算=[{saikeisan.Get(OptionalPhase.Black)}]
P2差分  =[{hyokati2}]
  再計算=[{saikeisan.Get(OptionalPhase.White)}]
";

            if (!safe)
            {
                syuturyoku.AppendLine(msg);
                {
                    var msg2 = syuturyoku.ToString();
                    syuturyoku.Clear();
                    Logger.Flush(msg2);
                }
            }
            Debug.Assert(safe, msg);
        }
Exemplo n.º 9
0
 /// <summary>
 /// 詰め手数を示していれば、真だぜ☆(^▽^)
 /// </summary>
 /// <param name="hyokati"></param>
 /// <returns></returns>
 public static bool InTumeTesu(Hyokati hyokati)
 {
     return
         ((Hyokati.TumeTesu_FuNoSu_ReiTeTumerare <= hyokati && hyokati <= Hyokati.TumeTesu_FuNoSu_HyakuTeTumerare)
          ||
          (Hyokati.TumeTesu_SeiNoSu_HyakuTeDume <= hyokati && hyokati <= Hyokati.TumeTesu_SeiNoSu_ReiTeDume)
         );
 }
Exemplo n.º 10
0
        /// <summary>
        /// 符号を反転したものを返す
        /// </summary>
        public HyokatiUtiwake ToHanten()
        {
            Hyokati edaBest2  = EdaBest; Conv_Hyokati.Hanten(ref edaBest2);
            Hyokati komawari2 = Komawari; Conv_Hyokati.Hanten(ref komawari2);
            Hyokati nikoma2   = Nikoma; Conv_Hyokati.Hanten(ref nikoma2);
            Hyokati okimari2  = Okimari; Conv_Hyokati.Hanten(ref okimari2);

            return(new HyokatiUtiwake(edaBest2, komawari2, nikoma2, okimari2, Riyu, RiyuHosoku));
        }
Exemplo n.º 11
0
 public JosekiMove(Move move, Move ousyu, Hyokati hyokati, int fukasa, int version, JosekiKyokumen owner)
 {
     this.Owner   = owner;
     this.Move    = move;
     this.Ousyu   = ousyu;
     this.Hyokati = hyokati;
     this.Fukasa  = fukasa;
     this.Version = version;
 }
Exemplo n.º 12
0
 /// <summary>
 /// 評価値、または 詰め手数を示していれば、真だぜ☆(^▽^)
 /// </summary>
 /// <param name="hyokati"></param>
 /// <returns></returns>
 public static bool InHyokatiOrTumeTesu(Hyokati hyokati)
 {
     return
         // 0手詰められ ~ 評価値 ~ 0手詰め
         (Hyokati.TumeTesu_FuNoSu_ReiTeTumerare <= hyokati
          &&
          hyokati <= Hyokati.TumeTesu_SeiNoSu_ReiTeDume
         );
 }
Exemplo n.º 13
0
 public HyokatiUtiwake(Hyokati edaBest, Hyokati komawari, Hyokati nikoma, Hyokati okimari, HyokaRiyu riyu, string riyuHosoku)
 {
     EdaBest    = edaBest;
     Komawari   = komawari;
     Nikoma     = nikoma;
     Okimari    = okimari;
     Riyu       = riyu;
     RiyuHosoku = riyuHosoku;
     Assert();
 }
Exemplo n.º 14
0
 /// <summary>
 /// 詰みの場合、数字をカウントアップするぜ☆(^▽^)
 /// </summary>
 /// <returns></returns>
 public static Hyokati CountUpTume(Hyokati hyokati)
 {
     if (Hyokati.TumeTesu_SeiNoSu_HyakuTeDume < hyokati)
     {
         hyokati = hyokati - 1; // 何手詰めの数字が大きくなるぜ☆
     }
     else if (hyokati < Hyokati.TumeTesu_FuNoSu_HyakuTeTumerare)
     {
         hyokati = hyokati + 1; // 何手詰められの数字が大きくなるぜ☆
     }
     return(hyokati);
 }
Exemplo n.º 15
0
        /// <summary>
        /// 評価値の計算し直し。
        ///
        /// 多対多の項目の組み合わせを全部加算。
        /// </summary>
        /// <param name="ky"></param>
        /// <returns>手番の視点で返す</returns>
        public void KeisanSinaosi(Kyokumen ky)
        {
            // 駒の位置(評価関数の項目番号)をリストに入れておくぜ☆
            Util_NikomaKankei.MakeKoumokuBangoHairetu_Subete(ky, Util_NikomaKankei.KoumokuBangoHairetu1);

            // 評価値
            int hyokati = 0;

            for (int iGyoIndex = 0; iGyoIndex < Util_NikomaKankei.KoumokuBangoHairetu1.Nagasa; iGyoIndex++)
            {
                for (int iRetuIndex = 0; iRetuIndex < Util_NikomaKankei.KoumokuBangoHairetu1.Nagasa; iRetuIndex++)
                {
                    if (Util_NikomaKankei.KoumokuBangoHairetu1.Hairetu[iGyoIndex] <= Util_NikomaKankei.KoumokuBangoHairetu1.Hairetu[iRetuIndex])// 組み合わせを反対から見ただけの同じものを弾くぜ☆(^~^)
                    {
                        continue;
                    }

                    // 差分更新と比較するので、差分更新用☆(^~^)
                    //hyokati += Util_NikomaKankei.GetHyokaNumber_SabunKosinYou(Util_NikomaKankei.KoumokuBangoHairetu1.Hairetu[iRetuIndex], Util_NikomaKankei.KoumokuBangoHairetu1.Hairetu[iGyoIndex]);
                    // (^▽^)関数(小さい数字,大きい数字)だぜ☆ そうでなければ逆立ちさせるぜ☆(^▽^)www
                    if (Util_NikomaKankei.KoumokuBangoHairetu1.Hairetu[iRetuIndex] < Util_NikomaKankei.KoumokuBangoHairetu1.Hairetu[iGyoIndex])
                    {
                        hyokati += Util_NikomaKankei.GetHyokaNumber_SabunKosinYou(Util_NikomaKankei.KoumokuBangoHairetu1.Hairetu[iRetuIndex], Util_NikomaKankei.KoumokuBangoHairetu1.Hairetu[iGyoIndex]);
                    }
                    else if (Util_NikomaKankei.KoumokuBangoHairetu1.Hairetu[iGyoIndex] < Util_NikomaKankei.KoumokuBangoHairetu1.Hairetu[iRetuIndex])
                    {
                        // 逆立ち☆(^▽^)www
                        hyokati += Util_NikomaKankei.GetHyokaNumber_SabunKosinYou(Util_NikomaKankei.KoumokuBangoHairetu1.Hairetu[iGyoIndex], Util_NikomaKankei.KoumokuBangoHairetu1.Hairetu[iRetuIndex]);
                    }
                }
            }

            if (hyokati < Util_NikomaKankei.SAISYO_HYOKATI_SABUNKOSINYOU)
            {
                hyokati = Util_NikomaKankei.SAISYO_HYOKATI_SABUNKOSINYOU;
            }
            else if (Util_NikomaKankei.SAIDAI_HYOKATI_SABUNKOSINYOU < hyokati)
            {
                hyokati = Util_NikomaKankei.SAIDAI_HYOKATI_SABUNKOSINYOU;
            }

            var(exists, phase) = ky.CurrentOptionalPhase.Match;
            if (exists)
            {
                if (phase == Phase.White)
                {
                    hyokati = -hyokati; // 対局者2視点に変えるぜ☆(^▽^)
                }
            }
            Hyokati = (Hyokati)hyokati;
        }
Exemplo n.º 16
0
        /// <summary>
        /// 定跡更新(ゲームセクション内)
        /// </summary>
        public static void Update2_JosekiToroku(Move bestMove, Hyokati bestHyokati, Kyokumen ky, StringBuilder syuturyoku)
        {
            if (Util_Machine.IsEnableBoardSize() && Option_Application.Optionlist.JosekiRec)
            {
                if (!IsJosekiTraced)// 定跡を使った指し手ではない場合に限り
                {
#if DEBUG
                    // 指し手の整合性をチェックしておきたいぜ☆(^▽^)
                    {
                        Kyokumen ky_forAssert = new Kyokumen();
                        int      caret_2      = 0;
                        if (!ky_forAssert.ParsePositionvalue(Option_Application.Optionlist.USI, KyFen_before, ref caret_2, true, false, out string moves, syuturyoku)) // ビットボードを更新したいので、適用する
                        {
                            syuturyoku.AppendLine("パースに失敗だぜ☆(^~^)! #鯰");
                            var msg = syuturyoku.ToString();
                            syuturyoku.Clear();
                            Logger.Flush(msg);
                            throw new Exception(msg);
                        }

                        if (!ky_forAssert.CanDoMove(bestMove, out MoveMatigaiRiyu riyu))
                        {
                            StringBuilder reigai1 = new StringBuilder();
                            reigai1.AppendLine("指せない指し手を定跡に登録しようとしたぜ☆(^~^)!:");
                            // reigai1.Append("理由:"); ConvMove.SetumeiLine(riyu, reigai1);
                            reigai1.Append("指し手:"); ConvMove.SetumeiLine(Option_Application.Optionlist.USI, bestMove, reigai1);
                            reigai1.Append("定跡にする1手前の局面 ("); reigai1.Append(KyFen_before); reigai1.AppendLine(")");
                            Util_Information.Setumei_Lines_Kyokumen(ky_forAssert, reigai1);
                            reigai1.AppendLine();
                            reigai1.Append("1手後は、現局面");
                            Util_Information.Setumei_Lines_Kyokumen(ky, reigai1);
                            syuturyoku.AppendLine(reigai1.ToString());
                            var msg = syuturyoku.ToString();
                            syuturyoku.Clear();
                            Logger.Flush(msg);
                            throw new Exception(msg);
                        }
                    }
#endif

                    Option_Application.Joseki.AddMove(KyFen_before, KyHash_before, OptionalPhaseBeforeMove, bestMove, bestHyokati, Util_Tansaku.NekkoKaranoFukasa, Util_Application.VERSION, syuturyoku);
                }
            }
        }
Exemplo n.º 17
0
        /// <summary>
        /// 局面に点数を付けるぜ☆(^▽^)
        ///
        /// どちらの対局者でも、自分に有利と思っていれば正の数の方向に点数が付くぜ☆(^▽^)
        /// </summary>
        /// <param name="ky_base"></param>
        /// <returns></returns>
        public void Tukurinaosi(Kyokumen.Sindanyo kys)
        {
            Hyokati[] hyokati = new Hyokati[] { Hyokati.Hyokati_Rei, Hyokati.Hyokati_Rei
                                                , Hyokati.Hyokati_Rei // 空白は手番なしで ここに入れるぜ☆(^~^)
            };

            // 盤上
            Bitboard komaBB = new Bitboard();

            for (int iTai = 0; iTai < Conv_Taikyokusya.AllOptionalPhaseList.Length; iTai++)
            {
                var optionalPhase = Conv_Taikyokusya.AllOptionalPhaseList[iTai];
                for (int iKs = 0; iKs < Conv_Komasyurui.Itiran.Length; iKs++)
                {
                    Komasyurui ks = Conv_Komasyurui.Itiran[iKs];

                    kys.ToSetIbasho(Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, optionalPhase), komaBB);
                    while (komaBB.Ref_PopNTZ(out Masu ms_jissai))
                    {
                        hyokati[iTai] += Conv_Koma.BanjoKomaHyokatiNumber[(int)Med_Koma.KomasyuruiAndTaikyokusyaToKoma(ks, optionalPhase)];
                    }
                }
            }

            // 持ち駒
            foreach (MotiKoma mk in Conv_MotiKoma.Itiran)
            {
                var            optionalPhase = Med_Koma.MotiKomaToPhase(mk);
                var            phaseIndex    = OptionalPhase.IndexOf(optionalPhase);
                MotiKomasyurui mks           = Med_Koma.MotiKomaToMotiKomasyrui(mk);
                Hyokati        komaHyokati   = Conv_Hyokati.KomaHyokati[(int)Med_Koma.MotiKomasyuruiAndPhaseToKoma(mks, optionalPhase)];

                hyokati[phaseIndex] += (int)komaHyokati * kys.CountMotikoma(mk);
            }

            // 手番 - 相手番
            Hyokati hyokatiP1 = hyokati[(int)Phase.Black];

            hyokati[(int)Phase.Black] -= hyokati[(int)Phase.White];
            hyokati[(int)Phase.White] -= hyokatiP1;
            KomawariHyokati_Sabun      = hyokati;
        }
Exemplo n.º 18
0
        public static void Assert_Sabun_Nikoma(string message, Kyokumen ky, StringBuilder syuturyoku)
        {
            Hyokati       current   = ky.Nikoma.Get(false);
            NikomaHyokati saikeisan = new NikomaHyokati();

            saikeisan.KeisanSinaosi(ky);

            bool   safe = Math.Abs(current - saikeisan.Hyokati) < 2; // 差分更新で 誤差 が出ると、どんどん溜まっていくぜ☆(^▽^)www
            string msg  = $"{message} 二駒評価値 差分更新 current =[{ current }] 再計算=[{ saikeisan }]";

            if (!safe)
            {
                syuturyoku.AppendLine(msg);
                {
                    var msg2 = syuturyoku.ToString();
                    syuturyoku.Clear();
                    Logger.Flush(msg2);
                }
            }
            Debug.Assert(safe, msg);
        }
Exemplo n.º 19
0
        public static void JohoMatome(
            int fukasa,
            Hyokati hyokasuToBack,
            StringBuilder hyoji
#if DEBUG
            , string hint
#endif
            )
        {
            if (Util_TimeManager.CanShowJoho())
            {
                PureAppli.dlgt_CreateJoho(
                    PureMemory.kifu_teban,
                    hyokasuToBack,
                    fukasa + 1,// 深さは 0 になっているので、Tansaku していない状態(=+1 して)に戻すぜ☆
                    HanpukuSinka.happaenoFukasa,
                    hyoji
#if DEBUG
                    , hint
#endif
                    );
                Util_TimeManager.DoneShowJoho();
            }
        }
Exemplo n.º 20
0
 public void Hanten()
 {
     this.Hyokati = (Hyokati)(-(int)this.Hyokati);
 }
Exemplo n.º 21
0
 public void Increase(Hyokati henkaRyo)
 {
     this.Hyokati += (int)henkaRyo;
 }
Exemplo n.º 22
0
        /// <summary>
        /// 定跡ファイルの容量を小さくしたいときに、定跡を削っていくぜ☆(^~^)
        /// </summary>
        /// <param name="removeBytes">減らしたいバイトサイズ☆(^▽^)</param>
        public long DownSizeing(long removeBytes)
        {
            long removed = 0;

            if (removeBytes < 1)
            {
                return(removed);
            }

            // 削る優先順
            // (1)バージョンが古い順、
            // (2)深さが浅い順、
            // (3)1つの局面の中で、2つ以上の指し手があり、評価値が一番悪い手、
            // (4)あとは泣く泣く適当に削る☆
            //
            // 最後に、指し手を持たない局面を削っておくぜ☆

            //────────────────────────────────────────
            // (1)バージョンが古い順
            //────────────────────────────────────────
            while (true)
            {
                // 全ての手を走査し、一番バージョン番号が古いもの☆(^▽^)
                int oldest = int.MaxValue;
                int newest = int.MinValue;
                foreach (JosekiKyokumen josekiKy in this.KyItems.Values)
                {
                    foreach (JosekiMove josekiSs in josekiKy.SsItems.Values)
                    {
                        if (josekiSs.Version < oldest)
                        {
                            oldest = josekiSs.Version;
                        }
                        else if (newest < josekiSs.Version)
                        {
                            newest = josekiSs.Version;
                        }
                    }
                }

                if (oldest == newest || newest < oldest)
                {
                    break;
                }

                foreach (JosekiKyokumen josekiKy in this.KyItems.Values)
                {
                    // バージョン番号が古いキーを列挙☆(^▽^)
                    List <Move> removee = new List <Move>();
                    foreach (KeyValuePair <Move, JosekiMove> entry in josekiKy.SsItems)
                    {
                        if (oldest == entry.Value.Version)
                        {
                            removee.Add(entry.Key);
                        }
                    }

                    // 列挙したキーに従って削除だぜ☆(^▽^)
                    foreach (Move key in removee)
                    {
                        int size = josekiKy.SsItems[key].ToString().Length;
                        josekiKy.SsItems.Remove(key);
                        removeBytes -= size;
                        removed     += size;
                        if (removeBytes < 1)
                        {
                            goto gt_FinishRemove;
                        }
                    }
                }
            }

            //────────────────────────────────────────
            // (2)深さが浅い順、
            //────────────────────────────────────────
            while (true)
            {
                // 全ての手を走査し、一番深さが浅いもの☆(^▽^)
                int shallowest = int.MaxValue;
                int deepest    = int.MinValue;
                foreach (JosekiKyokumen josekiKy in this.KyItems.Values)
                {
                    foreach (JosekiMove josekiSs in josekiKy.SsItems.Values)
                    {
                        if (josekiSs.Fukasa < shallowest)
                        {
                            shallowest = josekiSs.Fukasa;
                        }
                        else if (deepest < josekiSs.Fukasa)
                        {
                            deepest = josekiSs.Fukasa;
                        }
                    }
                }

                if (shallowest == deepest || deepest < shallowest)
                {
                    break;
                }

                // 深さが該当する手は消すぜ☆(^▽^)
                foreach (JosekiKyokumen josekiKy in this.KyItems.Values)
                {
                    // 浅いキーを列挙☆(^▽^)
                    List <Move> removee = new List <Move>();
                    foreach (KeyValuePair <Move, JosekiMove> entry in josekiKy.SsItems)
                    {
                        if (shallowest == entry.Value.Fukasa)
                        {
                            removee.Add(entry.Key);
                        }
                    }

                    // 列挙したキーに従って削除だぜ☆(^▽^)
                    foreach (Move key in removee)
                    {
                        int size = josekiKy.SsItems[key].ToString().Length;
                        josekiKy.SsItems.Remove(key);
                        removeBytes -= size;
                        removed     += size;
                        if (removeBytes < 1)
                        {
                            goto gt_FinishRemove;
                        }
                    }
                }
            }

            //────────────────────────────────────────
            // (3)1つの局面の中で、2つ以上の指し手があり、評価値が一番悪い手
            //────────────────────────────────────────
            foreach (JosekiKyokumen josekiKy in this.KyItems.Values)
            {
                if (2 <= josekiKy.SsItems.Count)
                {
                    // 全ての手を走査し、一番評価が悪いもの☆(^▽^)
                    Hyokati badest  = Hyokati.TumeTesu_SeiNoSu_ReiTeDume;
                    Hyokati goodest = Hyokati.TumeTesu_FuNoSu_ReiTeTumerare;

                    foreach (JosekiMove josekiSs in josekiKy.SsItems.Values)
                    {
                        if (josekiSs.Hyokati < badest)
                        {
                            badest = josekiSs.Hyokati;
                        }
                        else if (goodest < josekiSs.Hyokati)
                        {
                            goodest = josekiSs.Hyokati;
                        }
                    }

                    if (badest == goodest || goodest < badest)
                    {
                        break;
                    }

                    // 評価が悪いキーを列挙☆(^▽^)
                    List <Move> removee = new List <Move>();
                    foreach (KeyValuePair <Move, JosekiMove> entry in josekiKy.SsItems)
                    {
                        if (badest == entry.Value.Hyokati)
                        {
                            removee.Add(entry.Key);
                        }
                    }

                    // 列挙したキーに従って削除だぜ☆(^▽^)
                    foreach (Move key in removee)
                    {
                        int size = josekiKy.SsItems[key].ToString().Length;
                        josekiKy.SsItems.Remove(key);
                        removeBytes -= size;
                        removed     += size;
                        if (removeBytes < 1)
                        {
                            goto gt_FinishRemove;
                        }
                    }
                }
            }

            //────────────────────────────────────────
            // (4)あとは泣く泣く適当に削る☆
            //────────────────────────────────────────
            {
                // 全部のキーを列挙☆(^▽^)
                List <ulong> removee = new List <ulong>();
                foreach (KeyValuePair <ulong, JosekiKyokumen> entry in this.KyItems)
                {
                    removee.Add(entry.Key);
                }

                // 列挙したキーに従って削除だぜ☆(^▽^)
                foreach (ulong key in removee)
                {
                    int size = this.KyItems[key].ToString().Length;
                    this.KyItems.Remove(key);
                    removeBytes -= size;
                    removed     += size;
                    if (removeBytes < 1)
                    {
                        goto gt_FinishRemove;
                    }
                }
            }

gt_FinishRemove:
            //────────────────────────────────────────
            // (最後に)指し手を持たない局面を削る☆
            //────────────────────────────────────────
            {
                // 指し手を持たない局面のキーを列挙☆(^▽^)
                List <ulong> removee = new List <ulong>();
                foreach (KeyValuePair <ulong, JosekiKyokumen> entry in this.KyItems)
                {
                    if (entry.Value.SsItems.Count < 1)
                    {
                        removee.Add(entry.Key);
                    }
                }

                // 列挙したキーに従って削除だぜ☆(^▽^)
                foreach (ulong key in removee)
                {
                    this.KyItems.Remove(key);
                }
            }

            if (0 < removed)
            {
                this.Edited = true;
            }

            return(removed);
        }
Exemplo n.º 23
0
        /// <summary>
        /// 評価値の表示。
        /// 基本的に数字なんだが、数字の前に説明がつくことがあるぜ☆(^~^)
        /// 説明は各括弧で囲んであるぜ☆(^▽^)
        /// </summary>
        /// <param name="hyokaSu"></param>
        /// <param name="hyoji"></param>
        public static void Setumei(Hyokati hyokaSu, StringBuilder hyoji)
        {
            if (hyokaSu.tumeSu == Conv_Tumesu.None)
            {
                // スルー
            }
            else if (hyokaSu.IsKatu())
            {
                // 詰み手数が見えたときだぜ☆(^▽^)
                switch (PureSettei.fenSyurui)
                {
                case FenSyurui.sfe_n:
                {
                    hyoji.Append("mate ");
                    hyoji.Append(hyokaSu.GetKatu().ToString());
                }
                break;

                case FenSyurui.dfe_n:
                {
                    hyoji.Append("[katu ");
                    hyoji.Append(hyokaSu.GetKatu().ToString());
                    hyoji.Append("] ");
                    hyoji.Append(hyokaSu.ToString_Ten());
                }
                break;

                default:
                    throw new Exception(string.Format("未定義 {0}", PureSettei.fenSyurui));
                }
                return;
            }
            else if (hyokaSu.IsMakeru())
            {
                // 詰めを食らうぜ☆(>_<)
                switch (PureSettei.fenSyurui)
                {
                case FenSyurui.sfe_n:
                {
                    hyoji.Append("mate ");
                    hyoji.Append(hyokaSu.GetMakeru().ToString());
                }
                break;

                case FenSyurui.dfe_n:
                {
                    // 負数で出てくるのを、正の数に変換して表示するぜ☆(^▽^)
                    hyoji.Append("[makeru ");
                    hyoji.Append(hyokaSu.GetMakeru().ToString());
                    hyoji.Append("] ");
                    hyoji.Append(hyokaSu.ToString_Ten());
                }
                break;

                default:
                    throw new Exception(string.Format("未定義 {0}", PureSettei.fenSyurui));
                }
                return;
            }

            // 評価値☆
            hyoji.Append("cp ");
            hyoji.Append(hyokaSu.ToString_Ten());//enum型の名前が出ないように一旦int型に変換
        }
Exemplo n.º 24
0
        static PureMemory()
        {
            int taiLn = Conv_Taikyokusya.itiran.Length;

            #region 被王手判定
            // ビットボード
            hot_bb_checkerAr     = new Bitboard[taiLn];
            hot_bb_raion8KinboAr = new Bitboard[taiLn];
            hot_bb_nigemitiWoFusaideiruAiteNoKomaAr = new Bitboard[taiLn];
            hot_bb_nigereruAr = new Bitboard[taiLn];
            hot_bb_nigeroAr   = new Bitboard[taiLn];
            for (int iTai = 0; iTai < taiLn; iTai++)
            {
                hot_bb_checkerAr[iTai]     = new Bitboard();
                hot_bb_raion8KinboAr[iTai] = new Bitboard();
                hot_bb_nigemitiWoFusaideiruAiteNoKomaAr[iTai] = new Bitboard();
                hot_bb_nigereruAr[iTai] = new Bitboard();
                hot_bb_nigeroAr[iTai]   = new Bitboard();
            }

            hot_ms_raionAr             = new Masu[taiLn];
            hot_outeKomasCountAr       = new int[taiLn];
            hot_isNigerarenaiCheckerAr = new bool[taiLn];
            hot_raionCatchChosaAr      = new bool[taiLn];
            #endregion

            #region 指し手生成(シングルスレッドを想定)
            ssss_moveList             = new MoveList[PureMemory.MaxMoveDepth];
            ssss_moveListBad          = new MoveList[PureMemory.MaxMoveDepth];
            ssss_bbVar_idosaki_narazu = new Bitboard();
            ssss_bbVar_idosaki_nari   = new Bitboard();
            ssssTmp_bbVar_ibasho      = new Bitboard();

            ssss_bbBase_idosaki01_checker            = new Bitboard();
            ssss_bbBase_idosaki02_raionCatch         = new Bitboard();
            ssss_bbBase_idosaki03_nigeroTe           = new Bitboard();
            ssss_bbBase_idosaki04_try                = new Bitboard();
            ssss_bbBase_idosaki05_komaWoToruTe       = new Bitboard();
            ssss_bbBase_idosaki06_himodukiOteZasi    = new Bitboard();
            ssss_bbBase_idosaki07_suteOteZasi        = new Bitboard();
            ssss_bbBase_idosaki08_suteOteDa          = new Bitboard();
            ssss_bbBase_idosaki09_himodukiOteDa      = new Bitboard();
            ssss_bbBase_idosaki10_himodukiKanmanDa   = new Bitboard();
            ssss_bbBase_idosaki11_himodukiKanmanZasi = new Bitboard();
            ssss_bbBase_idosaki12_bottiKanmanZasi    = new Bitboard();
            ssss_bbBase_idosaki13_bottiKanmanDa      = new Bitboard();
            ssss_bbBase_idosaki14_suteKanmanZasi     = new Bitboard();
            ssss_bbBase_idosaki15_suteKanmanDa       = new Bitboard();

            ssss_movePickerWoNuketaBasho1 = "";

            for (int iFukasa = 0; iFukasa < PureMemory.MaxMoveDepth; iFukasa++)
            {
                ssss_moveList[iFukasa]    = new MoveList();
                ssss_moveListBad[iFukasa] = new MoveList();
            }
            #endregion

            #region ムーブス
            mvs_ssAr = new Move[KIFU_SIZE];
            #endregion
            #region 棋譜(コンピューター・プレイヤー同時に1つまで)
            kifu_syokiKyokumenFen = "";
            kifu_toraretaKsAr     = new Komasyurui[KIFU_SIZE];
            kifu_moveArray        = new Move[KIFU_SIZE];
            kifu_moveTypeArray    = new MoveType[KIFU_SIZE];
            // 手番☆(^~^)
            kifu_tebanAr_    = new Taikyokusya[KIFU_SIZE];
            kifu_aitebanAr_  = new Taikyokusya[KIFU_SIZE];
            kifu_nTebanAr_   = new int[KIFU_SIZE];
            kifu_nAitebanAr_ = new int[KIFU_SIZE];

            // 初期局面手番を未設定にしておいて、ResetTebanArray( ) すれば、手番配列の初期値が入るぜ☆(^~^)
            kifu_syokikyokumenTeban = Taikyokusya.Yososu;
            ResetTebanArray(Taikyokusya.T1);

            // 配列等の初期化が終わったあとで、手目をリセット
            ClearTeme(
                //kifu_syokikyokumenTeban
                );
            #endregion

            #region 現局面(棋譜カーソルが指している局面)(コンピューター・プレイヤー同時に1つまで)
            gky_kekka   = TaikyokuKekka.Karappo;
            gky_ky      = new Kyokumen();
            gky_hyokati = new Hyokati();
            Util_Control.UpdateRule(
#if DEBUG
                "static PureMemory"
#endif
                );
            #endregion

            #region 探索(tnsk)
            tnsk_kohoMove = Move.Toryo;
            #endregion
        }
Exemplo n.º 25
0
        /// <summary>
        /// 評価値の表示。
        /// 基本的に数字なんだが、数字の前に説明がつくことがあるぜ☆(^~^)
        /// 説明は各括弧で囲んであるぜ☆(^▽^)
        /// </summary>
        /// <param name="hyokati"></param>
        /// <param name="syuturyoku"></param>
        public static void Setumei(Hyokati hyokati, StringBuilder syuturyoku)
        {
            if (Conv_Hyokati.InSyokiti(hyokati))
            {
                if (Option_Application.Optionlist.USI)
                {
                    // USI
                    syuturyoku.Append(((int)hyokati).ToString());
                }
                else if (Hyokati.Syokiti_Alpha == hyokati)
                {
                    syuturyoku.Append($"[α未設定] {(int)hyokati}");
                }
                else if (Hyokati.Syokiti_Beta == hyokati)
                {
                    syuturyoku.Append("[β未設定] {(int)hyokati}");
                }
                else
                {
                    throw new Exception("予期しない初期値だぜ☆(^~^)");
                }
                return;
            }
            else if (Hyokati.TumeTesu_SeiNoSu_HyakuTeDume <= hyokati)
            {
                if (Hyokati.Sonota <= hyokati)
                {
                    // その他☆(^~^)
                    if (Option_Application.Optionlist.USI)
                    {
                        // USI
                        syuturyoku.Append("0");
                    }
                    else
                    {
                        switch (hyokati)
                        {
                        case Hyokati.Sonota_SyobuNasi:
                        {
                            syuturyoku.Append($"[SyobuNasi] {(int)hyokati}");
                        }
                        break;

                        default:
                        {
                            StringBuilder mojiretu1 = new StringBuilder();
                            mojiretu1.Append("[予期しない評価値だぜ☆(^~^) ");
                            Conv_Hyokati.Setumei(hyokati, mojiretu1);
                            mojiretu1.Append($"] {(int)hyokati}");

                            syuturyoku.AppendLine(mojiretu1.ToString());
                            throw new Exception(mojiretu1.ToString());
                        }
                        }
                    }
                }
                else
                {
                    // 詰み手数が見えたときだぜ☆(^▽^)
                    if (Option_Application.Optionlist.USI)
                    {
                        syuturyoku.Append("mate ");
                        syuturyoku.Append(((int)(Hyokati.TumeTesu_SeiNoSu_ReiTeDume - (int)hyokati)).ToString());
                    }
                    else
                    {
                        syuturyoku.Append("[katu ");
                        syuturyoku.Append(((int)(Hyokati.TumeTesu_SeiNoSu_ReiTeDume - (int)hyokati)).ToString());
                        syuturyoku.Append("] ");
                        syuturyoku.Append(((int)hyokati).ToString());
                    }
                }

                return;
            }
            else if (hyokati <= Hyokati.TumeTesu_FuNoSu_HyakuTeTumerare)
            {
                // 詰めを食らうぜ☆(>_<)
                if (Option_Application.Optionlist.USI)
                {
                    syuturyoku.Append("mate ");
                    syuturyoku.Append(((int)(Hyokati.TumeTesu_FuNoSu_ReiTeTumerare - (int)hyokati)).ToString());
                }
                else
                {
                    // 負数で出てくるのを、正の数に変換して表示するぜ☆(^▽^)
                    syuturyoku.Append("[makeru ");
                    syuturyoku.Append((-(int)(Hyokati.TumeTesu_FuNoSu_ReiTeTumerare - (int)hyokati)).ToString());
                    syuturyoku.Append("] ");
                    syuturyoku.Append(((int)hyokati).ToString());
                }
                return;
            }

            // 評価値☆
            syuturyoku.Append("cp ");
            syuturyoku.Append(((int)hyokati).ToString());//enum型の名前が出ないように一旦int型に変換
        }
Exemplo n.º 26
0
 /// <summary>
 /// 初期値なら、真だぜ☆(^▽^)説明用☆(^▽^)
 /// </summary>
 /// <param name="hyokati"></param>
 /// <returns></returns>
 public static bool InSyokiti(Hyokati hyokati)
 {
     return(Hyokati.Syokiti_Alpha == hyokati || Hyokati.Syokiti_Beta == hyokati);
 }
Exemplo n.º 27
0
 public void Increase(Option <Phase> optionalPhase, Hyokati henkaRyo)
 {
     this.KomawariHyokati_Sabun[OptionalPhase.IndexOf(optionalPhase)] += (int)henkaRyo;
 }
Exemplo n.º 28
0
        /// <summary>
        /// 評価値を更新するぜ☆(^▽^)
        /// </summary>
        /// <param name="erandaSasite">実際に選んだ指し手☆</param>
        /// <param name="erandaHyokati">実際に選んだ手の評価値☆</param>
        public static void Update(Move erandaSasite, Hyokati erandaHyokati, Kyokumen ky, StringBuilder syuturyoku)
        {
            JosekiKyokumen joKy_orNull = Option_Application.Joseki.GetKyokumen(Util_KikaiGakusyu.KaisiKyHash);

            if (null == joKy_orNull)// この局面の定跡データが入っていなければ、そもそも 学習できないぜ☆(^▽^)
            {
                return;
            }


            // 成績表を見て、現局面で最も勝率の高い指し手を、教師とするぜ☆(^~^)

            Move kyosiSs = Option_Application.Seiseki.GetSasite_Winest(ky, out float kyosiSyoritu_notUse);

            Hyokati kyosiHyokati;                                         // 教師の手の評価値☆

            if (Util_KikaiGakusyu.FirstAndHappaFens.ContainsKey(kyosiSs)) // 教師の手はあるはずだろ☆(^~^)?
            {
                // まず、一手指すぜ☆
                Nanteme nanteme = new Nanteme();
                ky.DoMove(Option_Application.Optionlist.USI, kyosiSs, MoveType.N00_Karappo, ref nanteme, ky.CurrentOptionalPhase, syuturyoku);

                // 評価値を調べようぜ☆(^▽^)
                Hyokati komawariHyokati = ky.Komawari.Get(ky.CurrentOptionalPhase);
                Hyokati nikomaHyokati   = ky.Nikoma.Get(true);
                kyosiHyokati = (int)komawariHyokati + nikomaHyokati;


                // 一手戻そうぜ☆(^▽^)
                ky.UndoMove(Option_Application.Optionlist.USI, kyosiSs, syuturyoku);
            }
            else
            {
                return;
            }
            // 教師の手の評価値が、一番高いとは限らないぜ☆(^~^)

            if (!Conv_Hyokati.InHyokati(kyosiHyokati))
            {
                // 教師の評価値が、メートの数字などになっている場合は、学習はできないぜ☆(>_<)
                return;
            }



            Kyokumen happaKy = new Kyokumen();
            int      caret_temp2;
            double   sumSigmoidY = 0.0d;// 積分☆


            // 深さが異なるので、自分の局面、相手の局面 の数も異なり、
            // 足す局面と、引く局面の数が合わなくなるぜ☆(^~^)
            // ↓
            // せっかく 1P、2P の評価値を持っているのだから、
            // 1P から引いた分は 2P に足す、ということでどうか☆(^~^)?


            // では、今回の合法手を全て見ていくぜ☆(^~^)
            foreach (KeyValuePair <Move, List <string> > entry in Util_KikaiGakusyu.FirstAndHappaFens)
            {
                if (entry.Key == kyosiSs)
                {
                    // 教師の手は、今回はスルーするぜ☆(^▽^)
                    continue;
                }
                // さて、教師以外の手だが……☆(^~^)

                HyokatiUtiwake sonotanoTe_hyokatiUtiwake;

                // まず、一手指すぜ☆
                Nanteme nanteme = new Nanteme();
                ky.DoMove(Option_Application.Optionlist.USI, entry.Key, MoveType.N00_Karappo, ref nanteme, ky.CurrentOptionalPhase, syuturyoku);

                // 評価値を調べようぜ☆(^▽^)
                ky.Hyoka(out sonotanoTe_hyokatiUtiwake, HyokaRiyu.Yososu, true// ランダムな局面で学習したりもするし☆(^~^)
                         );

                // 一手戻そうぜ☆(^▽^)
                ky.UndoMove(Option_Application.Optionlist.USI, entry.Key, syuturyoku);

                if (!Conv_Hyokati.InHyokati(sonotanoTe_hyokatiUtiwake.EdaBest))
                {
                    // その他の手の評価値が、メートの数字などになっている場合は、学習はできないぜ☆(>_<)
                    continue;
                }

                // 教師の手と、それ以外の手の 評価値の差を、
                // シグモイドの x に当てはめて、y を求めるぜ☆
                double sigmoidY = Option_Application.Optionlist.NikomaGakusyuKeisu * Util_Sigmoid.Sigmoid(erandaHyokati - kyosiHyokati);
                // 教師の手(=一番評価値が高い手)より 評価値が上回っている手は、
                // すると、 0.5 < y < 1 となるな☆
                // 下回っていれば、
                // 0 < y < 0.5 となるな☆

                var(exists1, phase1) = Util_Tansaku.StartingPhase.Match;
                var(exists2, phase2) = happaKy.CurrentOptionalPhase.Match;

                // この点数を、葉 から かき集めるぜ☆www(^▽^)
                foreach (string happaFen in entry.Value)
                {
                    caret_temp2 = 0;
                    happaKy.ParsePositionvalue(Option_Application.Optionlist.USI, happaFen, ref caret_temp2, false, false, out string moves, syuturyoku);

                    // この局面の2駒関係を、シグモイドの y 点分、下げるぜ☆
                    sumSigmoidY += Util_NikomaKankei.DecrementParamerter_KikaiGakusyu(
                        happaKy,
                        (exists1 && exists2 && phase1 == phase2) ? -sigmoidY : sigmoidY//自分の手番なら 引く☆
                        );
                }
            }

            // 下げてかき集めた シグモイドの y の量を、
            // 教師の指し手の葉に 山分けするぜ☆(^▽^)
            double yamawake = sumSigmoidY / (double)Util_KikaiGakusyu.FirstAndHappaFens[kyosiSs].Count;

            foreach (string happaFen in Util_KikaiGakusyu.FirstAndHappaFens[kyosiSs])// 教師の手はあるはずだろ☆(^~^)?
            {
                caret_temp2 = 0;
                happaKy.ParsePositionvalue(Option_Application.Optionlist.USI, happaFen, ref caret_temp2, false, false, out string moves, syuturyoku);

                var(exists1, phase1) = Util_Tansaku.StartingPhase.Match;
                var(exists2, phase2) = happaKy.CurrentOptionalPhase.Match;

                // 各葉に 山分けだぜ☆(^~^)
                Util_NikomaKankei.IncrementParamerter_KikaiGakusyu(
                    happaKy,
                    (exists1 && exists2 && phase1 == phase2) ? -yamawake : yamawake//自分の手番なら 足すぜ☆
                    );
            }
        }
Exemplo n.º 29
0
 /// <summary>
 /// 評価値の変域内なら真だぜ☆(^▽^)
 /// </summary>
 /// <returns></returns>
 public static bool InHyokati(Hyokati hyokati)
 {
     return(Hyokati.Hyokati_Saisyo <= hyokati && hyokati <= Hyokati.Hyokati_Saidai);
 }
Exemplo n.º 30
0
        /// <summary>
        /// 探索だぜ☆(^▽^)
        /// </summary>
        /// <param name="ky"></param>
        /// <param name="alpha"></param>
        /// <param name="fukasa">カウントダウン式の数字☆(^▽^) 反復深化探索の1週目の初期値は 1、2週目の初期値は 2 だぜ☆(^▽^)
        /// これがどんどんカウントダウンしていくぜ☆(^▽^) 0 で呼び出されたときは葉にしてすぐ処理を終われよ☆(^▽^)www</param>
        /// <param name="out_yomisujiToBack"></param>
        /// <param name="out_bestHyokatiAb1">手番から見た指し手の評価値だぜ☆(^~^)</param>
        /// <param name="out_edaBest_Komawari_JohoNoTame">内訳の目視確認用に使うだけの項目。</param>
        /// <param name="out_edaBest__Okimari_JohoNoTame">内訳の目視確認用に使うだけの項目。</param>
        /// <param name="out_edaBest_____Riyu_JohoNoTame">内訳の目視確認用に使うだけの項目。</param>
        /// <param name="dlgt_CreateJoho"></param>
        /// <returns></returns>
        private static void Tansaku_(
            out Move out_bestMove,
            out Hyokati out_bestHyokasu // 手番側の指し手の評価値だぜ☆(^~^)
            )
        {
            Debug.Assert(0 <= PureMemory.tnsk_fukasa && PureMemory.tnsk_fukasa < PureMemory.ssss_moveList.Length, "");

            out_bestMove    = Move.Toryo;
            out_bestHyokasu = null;

            //────────────────────────────────────────
            // 時間切れ判定
            //────────────────────────────────────────
            if (ComSettei.timeManager.IsTimeOver_TansakuChu())
            {
                out_bestMove    = Move.Toryo;
                out_bestHyokasu = new Hyokati(
                    Conv_Hyokati.Hyokati_Rei,
                    Conv_Tumesu.Stalemate,
                    true // 今回の探索の結果は破棄するぜ☆(^~^)
#if DEBUG
                    , Conv_Hyokati.Hyokati_Rei
                    , Conv_Hyokati.Hyokati_Rei
                    , Conv_Hyokati.Hyokati_Rei
                    , HyokaRiyu.JikanGire
                    , ""
#endif
                    );
#if DEBUG
                Util_Tansaku.Snapshot("時間切れだぜ☆(^~^)", out_bestMove);
#endif
                return;
            }

            //────────────────────────────────────────
            // 葉
            //────────────────────────────────────────
            #region 葉
            if (
                // 深さ0 で呼び出されたときは、葉にしろということだぜ☆(^▽^)www
                PureMemory.tnsk_fukasa == 0
                )
            {
                // 深さ(根っこからの深さ)は 1 以上で始まるから、ループの1週目は、スルーされるはずだぜ☆(^▽^)
                // 1手指して 枝を伸ばしたとき、相手の手番の局面になっているな☆(^▽^)そのとき ここを通る可能性があるぜ☆

                //
                // 末端局面で評価値を作らないぜ☆(^~^)!
                // 指し手を、指したときに作るんだぜ☆(^~^)!
                //

                PureMemory.tnsk_happaTeme = PureMemory.kifu_endTeme;

                // 「手目」カーソルは DoMove で1つ進んでいるはずなので、戻すんだぜ☆(^~^)
                out_bestMove    = PureMemory.kifu_moveArray[PureMemory.kifu_endTeme - 1];
                out_bestHyokasu = new Hyokati(PureMemory.gky_hyokati);


                // 葉で情報表示
                Util_Joho.JohoMatome(
                    PureMemory.tnsk_fukasa + 1,
                    out_bestHyokasu,
                    PureMemory.tnsk_hyoji
#if DEBUG
                    , out_bestHyokasu.dbg_riyu.ToString()
#endif
                    );
#if DEBUG
                Util_Tansaku.Snapshot("葉だぜ☆(^~^)", out_bestMove);
#endif
                return;//枝を戻る(正常終了)
            }
            #endregion

            //────────────────────────────────────────
            // 指し手生成
            //────────────────────────────────────────
            // グローバル変数 Util_MoveSeisei.Sslist に指し手がセットされるぜ☆(^▽^)
            MoveGenAccessor.DoMovePickerBegin(MoveType.N21_All);
            MovePicker01.MovePickerN01(MoveType.N21_All, true);

            #region ステイルメイト
            //────────────────────────────────────────
            // ステイル・メイト
            //────────────────────────────────────────
            if (PureMemory.ssss_moveList[PureMemory.tnsk_fukasa].listCount < 1)
            {
                // 詰んでるぜ☆(^~^)
                out_bestMove    = Move.Toryo;
                out_bestHyokasu = new Hyokati(
                    Conv_Hyokati.Hyokati_Rei,
                    Conv_Tumesu.Stalemate,
                    false
#if DEBUG
                    , Conv_Hyokati.Hyokati_Rei
                    , Conv_Hyokati.Hyokati_Rei
                    , Conv_Hyokati.Hyokati_Rei
                    , HyokaRiyu.Stalemate
                    , ""
#endif
                    );

                // ステイルメイトで情報表示
                Util_Joho.JohoMatome(
                    PureMemory.tnsk_fukasa + 1,// 深さは 0 になっているので、Tansaku していない状態(=+1 して)に戻すぜ☆
                    out_bestHyokasu,
                    PureMemory.tnsk_hyoji
#if DEBUG
                    , "Stalemate"
#endif
                    );
#if DEBUG
                Util_Tansaku.Snapshot("ステイルメイトだぜ☆(^~^)", out_bestMove);
                MoveSeiseiAccessor.DumpMoveSeisei(PureMemory.tnsk_hyoji);
#endif
                return;//枝を戻る(正常終了)
            }
            #endregion


            for (int iSs = 0; iSs < PureMemory.ssss_moveList[PureMemory.tnsk_fukasa].listCount; iSs++)
            {
                // 枝☆ 適当にここらへんでカウントアップするかだぜ☆(^~^)
                PureMemory.tnsk_tyakusyuEdas++;



                //────────────────────────────────────────
                // 指す
                //────────────────────────────────────────

//#if DEBUG
//                Util_Tansaku.Snapshot("ドゥ前", hyoji);
//#endif

                Move     ss_jibun     = PureMemory.ssss_moveList[PureMemory.tnsk_fukasa].moveList[iSs];
                MoveType ssType_jibun = PureMemory.ssss_moveList[PureMemory.tnsk_fukasa].moveTypeList[iSs];

                if (DoMoveOpe.TryFailDoMoveAll(
                        ss_jibun,
                        ssType_jibun
#if DEBUG
                        , PureSettei.fenSyurui
                        , (IDebugMojiretu)PureMemory.tnsk_hyoji
                        , false
                        , "TryFail_Tansaku_(1)"
#endif
                        ))
                {
                    // 探索時にエラーが起こった場合は強制終了☆(^~^)
                    throw new Exception(PureMemory.tnsk_hyoji.ToString());
                }
                // 手番を進めるぜ☆(^~^)
                MoveGenAccessor.AddKifu(
                    ss_jibun,
                    ssType_jibun,
                    PureMemory.dmv_ks_c);
#if DEBUG
                Util_Tansaku.Snapshot("ドゥ後・探索前", out_bestMove);
#endif

                Move ss_aite;
                //MoveType eda_moveType;
                // goto文で飛ぶと未割当になるので、ヌルでも入れておくぜ☆(^~^)
                Hyokati hyokasu_aiteToJibun = null;

                // この指し手が、駒を取った手かどうか☆

                PureMemory.SetTnskHyoji(PureMemory.tnsk_hyoji);
                // 探索者がプラスでスタートして、
                // 探索者の反対側はマイナスになり、
                // 探索者の反対側の反対側はプラスに戻るぜ☆(^▽^)
                PureMemory.DecreaseTnskFukasa();
                Tansaku_(
                    out ss_aite,
                    out hyokasu_aiteToJibun
                    // 相手番の指し手の評価値が入ってくるぜ☆(^~^)
                    );
                PureMemory.IncreaseTnskFukasa();
//#if DEBUG
//                Util_Tansaku.Snapshot("探索後・アンドゥ前", hyoji);
//#endif

                //────────────────────────────────────────
                // 詰みを発見していれば、打ち切りフラグを立てるぜ☆(*^~^*)
                //────────────────────────────────────────
                bool undoAndBreak = false;
                if (hyokasu_aiteToJibun.tumeSu == Conv_Tumesu.CatchRaion)
                {
                    out_bestMove    = ss_jibun;
                    out_bestHyokasu = new Hyokati(
                        Conv_Hyokati.Hyokati_Rei,
                        Conv_Tumesu.CatchRaion,// この枝にこれるようなら、勝ち宣言だぜ☆(^▽^)
                        false
                #if DEBUG
                        , Conv_Hyokati.Hyokati_Rei
                        , Conv_Hyokati.Hyokati_Rei
                        , Conv_Hyokati.Hyokati_Rei
                        , HyokaRiyu.TansakuRaionCatch
                        , ""
                #endif
                        );
                    // 打ち切りで情報表示
                    Util_Joho.JohoMatome(
                        PureMemory.tnsk_fukasa,
                        out_bestHyokasu,
                        PureMemory.tnsk_hyoji
#if DEBUG
                        , "TansakuRaionCatch"
#endif
                        );

                    // 詰みではなく、らいおんきゃっち または トライかを 調べるぜ☆(^~^)
                    // この手番は、
                    // この指し手を選べば、勝てるという理屈だが……☆
                    undoAndBreak = true;
#if DEBUG
                    Util_Tansaku.Snapshot("らいおんキャッチだぜ☆(^~^)", out_bestMove);
#endif
                }

                // 探索で先の枝から戻ってきたときは、評価の符号を反転し、詰め手数のカウントもアップするぜ☆(^~^)
                hyokasu_aiteToJibun.CountUpTume();
                hyokasu_aiteToJibun.ToHanten();



                if (UndoMoveOpe.TryFailUndoMove(
#if DEBUG
                        PureSettei.fenSyurui
                        , (IDebugMojiretu)PureMemory.tnsk_hyoji
#endif
                        ))
                {
                    // 探索時にエラーが起こった場合は強制終了☆(^~^)
                    throw new Exception(PureMemory.tnsk_hyoji.ToString());
                }

#if DEBUG
                Util_Tansaku.Snapshot("アンドゥ後", out_bestMove);
#endif

                //────────────────────────────────────────
                // これ以上 弟要素を探索するのを止め、枝を戻るかどうか☆(^~^)
                //────────────────────────────────────────
                #region 打ち切り各種
                if (undoAndBreak)
                {
                    // (1)千日手の権利を相手に渡すために低点数付け<それ以降の手は読まない>
                    // (2)らいおん を捕獲した
                    // (3)トライ した
#if DEBUG
                    Util_Tansaku.Snapshot("アンドゥ後ブレイクだぜ☆(^~^)", out_bestMove);
#endif
                    break;//枝を戻る(正常終了)
                }
                #endregion

                //────────────────────────────────────────
                // アップデート・枝ベスト
                //────────────────────────────────────────
                #region アップデート・枝ベスト

                // 点数が付かないことがあって、その場合 ベスト指し手 を1度も選ばない
                // 「<=」にすると同点だったら、指し手のオーダリングの低いのを選ぶが☆(^~^)
                if (null == out_bestHyokasu)
                {
                    out_bestMove    = ss_jibun;
                    out_bestHyokasu = hyokasu_aiteToJibun;// new HyokaSu(eda_hyokasu);//ここで新規作成
#if DEBUG
                    Util_Tansaku.Snapshot("アップデート枝ベスト1回目だぜ☆(^~^)", out_bestMove);
#endif
                }
                else if (out_bestHyokasu.hyokaTen < hyokasu_aiteToJibun.hyokaTen)
                {
                    out_bestMove = ss_jibun;
                    out_bestHyokasu.ToSet(hyokasu_aiteToJibun);

                    // 兄弟の中で一番の読み筋だぜ☆(^▽^)
                    // ↓
                    // TODO: ここで情報を表示したいが……☆(^~^)
#if DEBUG
                    Util_Tansaku.Snapshot("アップデート枝ベストだぜ☆(^~^)", out_bestMove);
#endif
                }
                #endregion
            }//指し手ループ
             //;

            // このノードでの最大評価を返すんだぜ☆(^▽^)
            // ここでアルファを返してしまうと、アルファが1回も更新されなかったときに、このノードの最大評価ではないものを返してしまうので不具合になるぜ☆(^~^)

            if (null == out_bestHyokasu)
            {
                out_bestMove    = Move.Toryo;
                out_bestHyokasu = new Hyokati(
                    Conv_Hyokati.Hyokati_Rei,
                    Conv_Tumesu.None,
                    false
#if DEBUG
                    , Conv_Hyokati.Hyokati_Rei
                    , Conv_Hyokati.Hyokati_Rei
                    , Conv_Hyokati.Hyokati_Rei
                    , HyokaRiyu.Fumei
                    , "ループ抜け"
#endif
                    );

                // ステイルメイトで情報表示
                Util_Joho.JohoMatome(
                    PureMemory.tnsk_fukasa,
                    out_bestHyokasu,
                    PureMemory.tnsk_hyoji
#if DEBUG
                    , "LoopOut"
#endif
                    );

#if DEBUG
                Util_Tansaku.Snapshot("評価の決まらない、ループ抜けだぜ☆(^~^)", out_bestMove);
#endif
                return;//枝を戻る(正常終了)
            }
        }