Пример #1
0
        public static string BoardFileLog_ToJsonStr(GraphicalLog_File boardFileLog1)
        {
            StringBuilder sb_json_boardsLog = new StringBuilder();

            foreach (GraphicalLog_Board boardLog1 in boardFileLog1.boards)
            {
                // 指し手。分かれば。
                string moveStr = Converter04.MoveToStringForLog(boardLog1.moveOrNull, boardLog1.GenTeban);

                //string oldCaption = boardLog1.Caption;
                //boardLog1.Caption += "_" + moveStr;
                sb_json_boardsLog.Append(boardLog1.ToJsonStr());
                //boardLog1.Caption = oldCaption;
            }

            return(sb_json_boardsLog.ToString());
        }
Пример #2
0
        /// <summary>
        /// ハブノードの次手番の局面のうち、王手がかかった局面は取り除きます。
        /// </summary>
        public static void LAA_RemoveNextNode_IfMate(
            Node <ShootingStarlightable, KyokumenWrapper> hubNode,
            bool enableLog,
            int yomuDeep,                   //脳内読み手数
            int tesumi_yomiGenTeban_forLog, //読み進めている現在の手目
            Playerside pside_genTeban,
            GraphicalLog_File logF_kiki
            )
        {
            // Node<,>の形で。
            Dictionary <string, Node <ShootingStarlightable, KyokumenWrapper> > newNextNodes = new Dictionary <string, Node <ShootingStarlightable, KyokumenWrapper> >();

            hubNode.Foreach_NextNodes((string key, Node <ShootingStarlightable, KyokumenWrapper> node, ref bool toBreak) =>
            {
                System.Diagnostics.Debug.Assert(node.Key != null);//指し手がヌルなはず無いはず。

                // 王様が利きに飛び込んだか?
                bool kingSuicide = Util_LegalMove.LAAA_KingSuicide(
                    enableLog,
                    node.Value.ToKyokumenConst,
                    yomuDeep,
                    tesumi_yomiGenTeban_forLog,
                    pside_genTeban,//現手番=攻め手視点
                    logF_kiki,
                    node.Key
                    );

                if (!kingSuicide)
                {
                    // 王様が利きに飛び込んでいない局面だけ、残します。
                    if (newNextNodes.ContainsKey(key))
                    {
                        newNextNodes[key] = node;
                    }
                    else
                    {
                        newNextNodes.Add(key, node);
                    }
                }
            });


            // 入替え
            hubNode.Set_NextNodes(newNextNodes);
        }
Пример #3
0
        /// <summary>
        /// 指定された局面で、指定された手番の駒の、利きマスを算出します。
        /// 持ち駒は盤上にないので、利きを調べる必要はありません。
        ///
        /// 「手目」は判定できません。
        ///
        /// </summary>
        /// <param name="kouho"></param>
        /// <param name="sbGohosyu"></param>
        /// <param name="logger"></param>
        public static List_OneAndMulti <Finger, SySet <SyElement> > LAAAA_GetEffect(
            bool enableLog,
            bool isHonshogi,
            SkyConst src_Sky,
            Playerside pside_genTeban3,
            bool isAiteban,
            GraphicalLog_File logF_kiki,
            string logBrd_caption,
            int yomuDeep_forLog,//脳内読み手数
            int tesumi_yomiCur_forLog,
            ShootingStarlightable move_forLog
            )
        {
            GraphicalLog_Board logBrd_kiki = new GraphicalLog_Board();

            logBrd_kiki.Caption        = logBrd_caption;// "利き_"
            logBrd_kiki.Tesumi         = tesumi_yomiCur_forLog;
            logBrd_kiki.NounaiYomiDeep = yomuDeep_forLog;
            //logBrd_kiki.Score = 0.0d;
            logBrd_kiki.GenTeban = pside_genTeban3;// 現手番
            logF_kiki.boards.Add(logBrd_kiki);

            // 《1》
            List_OneAndMulti <Finger, SySet <SyElement> > sMs_effect = new List_OneAndMulti <Finger, SySet <SyElement> >();//盤上の駒の利き

            {
                // 《1.1》
                Playerside tebanSeme;  //手番(利きを調べる側)
                Playerside tebanKurau; //手番(喰らう側)
                {
                    if (isAiteban)
                    {
                        tebanSeme  = Converter04.AlternatePside(pside_genTeban3);
                        tebanKurau = pside_genTeban3;
                    }
                    else
                    {
                        tebanSeme  = pside_genTeban3;
                        tebanKurau = Converter04.AlternatePside(pside_genTeban3);
                    }

                    if (Playerside.P1 == tebanSeme)
                    {
                        logBrd_kiki.NounaiSeme = Gkl_NounaiSeme.Sente;
                    }
                    else if (Playerside.P2 == tebanSeme)
                    {
                        logBrd_kiki.NounaiSeme = Gkl_NounaiSeme.Gote;
                    }
                }


                // 《1.2》
                Fingers fingers_seme_IKUSA;  //戦駒(利きを調べる側)
                Fingers fingers_kurau_IKUSA; //戦駒(喰らう側)
                Fingers dust1;
                Fingers dust2;

                Util_Things.AAABAAAA_SplitGroup(
                    out fingers_seme_IKUSA,
                    out fingers_kurau_IKUSA,
                    out dust1,
                    out dust2,
                    src_Sky,
                    tebanSeme,
                    tebanKurau
                    );


                // 攻め手の駒の位置
                GraphicalLog_Board boardLog_clone = new GraphicalLog_Board(logBrd_kiki);
                foreach (Finger finger in fingers_seme_IKUSA.Items)
                {
                    RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(finger).Now);


                    Gkl_KomaMasu km = new Gkl_KomaMasu(
                        Util_GraphicalLog.PsideKs14_ToString(tebanSeme, Haiyaku184Array.Syurui(koma.Haiyaku), ""),
                        Util_Masu.AsMasuNumber(koma.Masu)
                        );
                    boardLog_clone.KomaMasu1.Add(km);
                }

                foreach (Finger finger in fingers_kurau_IKUSA.Items)
                {
                    RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(finger).Now);


                    logBrd_kiki.KomaMasu2.Add(new Gkl_KomaMasu(
                                                  Util_GraphicalLog.PsideKs14_ToString(tebanKurau, Haiyaku184Array.Syurui(koma.Haiyaku), ""),
                                                  Util_Masu.AsMasuNumber(koma.Masu)
                                                  ));
                }

                logBrd_kiki = boardLog_clone;



                // 《1.3》
                SySet <SyElement> masus_seme_IKUSA  = Converter04.Fingers_ToMasus(fingers_seme_IKUSA, src_Sky);  // 盤上のマス(利きを調べる側の駒)
                SySet <SyElement> masus_kurau_IKUSA = Converter04.Fingers_ToMasus(fingers_kurau_IKUSA, src_Sky); // 盤上のマス(喰らう側の駒)

                // 駒のマスの位置は、特にログに取らない。

                // 《1.4》
                Maps_OneAndOne <Finger, SySet <SyElement> > kmEffect_seme_IKUSA = Util_Things.Get_KmEffect_seme_IKUSA(
                    fingers_seme_IKUSA,//この中身がおかしい。
                    masus_seme_IKUSA,
                    masus_kurau_IKUSA,
                    src_Sky,
                    enableLog,
                    Converter04.MoveToStringForLog(move_forLog, pside_genTeban3)
                    );// 利きを調べる側の利き(戦駒)

                // 戦駒の利き
                logBrd_kiki = new GraphicalLog_Board(logBrd_kiki);
                kmEffect_seme_IKUSA.Foreach_Entry((Finger key, SySet <SyElement> value, ref bool toBreak) =>
                {
                    RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(key).Now);


                    string komaImg = Util_GraphicalLog.PsideKs14_ToString(tebanSeme, Haiyaku184Array.Syurui(koma.Haiyaku), "");

                    foreach (Basho masu in value.Elements)
                    {
                        boardLog_clone.Masu_theEffect.Add((int)masu.MasuNumber);
                    }
                });

                logBrd_kiki = boardLog_clone;


                // 《1》 = 《1.4》の戦駒+持駒
                sMs_effect.AddRange_New(kmEffect_seme_IKUSA);
            }

            return(sMs_effect);
        }
Пример #4
0
        /// <summary>
        /// 指定された手の中から、王手局面を除外します。
        ///
        /// 王手回避漏れを防ぎたいんだぜ☆
        /// </summary>
        /// <param name="km_available">自軍の各駒の移動できる升セット</param>
        /// <param name="sbGohosyu"></param>
        /// <param name="logTag"></param>
        public static KifuNode LA_RemoveMate(
            bool isHonshogi,
            Maps_OneAndMulti <Finger, ShootingStarlightable> genTeban_komabetuAllMove1, // 現手番の、どの駒が、どんな手を指すことができるか
            int yomuDeep,                                                               //脳内読み手数
            int tesumi_yomiGenTeban,
            Playerside pside_yomiGenTeban,
            KifuNode siteiNode_yomiGenTeban,
            bool enableLog,
            GraphicalLog_File logF_kiki,
            string hint)
        {
            Node <ShootingStarlightable, KyokumenWrapper> hubNode = UtilKomabetuMove.ToNextNodes_AsHubNode(
                genTeban_komabetuAllMove1, siteiNode_yomiGenTeban, pside_yomiGenTeban
                );                                                    // ハブ・ノード自身はダミーノードなんだが、子ノードに、次のノードが入っている。

            Converter04.AssertNariMove(hubNode, "#LA_RemoveMate(1)"); //ここはok
            Util_LegalMove.Log1(hubNode, enableLog, tesumi_yomiGenTeban, hint);


            if (isHonshogi)
            {
                // 王手が掛かっている局面を除きます。

                Util_LegalMove.LAA_RemoveNextNode_IfMate(
                    hubNode,
                    enableLog,
                    yomuDeep,
                    tesumi_yomiGenTeban,
                    pside_yomiGenTeban,
                    logF_kiki);
            }
            Converter04.AssertNariMove(hubNode, "#LA_RemoveMate(2)王手局面削除直後");//ここはok


            // 「指し手一覧」を、「駒別の全指し手」に分けます。
            Maps_OneAndMulti <Finger, ShootingStarlightable> komabetuAllMoves2 = siteiNode_yomiGenTeban.SplitMoveByKoma(hubNode);

            Converter04.AssertNariMove(komabetuAllMoves2, "#LA_RemoveMate(3)更に変換後");//ここはok

            //
            // 「駒別の指し手一覧」を、「駒別の進むマス一覧」になるよう、データ構造を変換します。
            //
            Maps_OneAndOne <Finger, SySet <SyElement> > komabetuSusumuMasus = new Maps_OneAndOne <Finger, SySet <SyElement> >();// 「どの駒を、どこに進める」の一覧

            foreach (KeyValuePair <Finger, List <ShootingStarlightable> > entry in komabetuAllMoves2.Items)
            {
                Finger finger = entry.Key;
                List <ShootingStarlightable> teList = entry.Value;

                // ポテンシャル・ムーブを調べます。
                SySet <SyElement> masus_PotentialMove = new SySet_Default <SyElement>("ポテンシャルムーブ");
                foreach (ShootingStarlightable te in teList)
                {
                    RO_Star_Koma koma = Util_Koma.AsKoma(te.Now);

                    masus_PotentialMove.AddElement(koma.Masu);
                }

                if (!masus_PotentialMove.IsEmptySet())
                {
                    // 空でないなら
                    Util_KomabetuMasus.AddOverwrite(komabetuSusumuMasus, finger, masus_PotentialMove);
                }
            }

            // まず、ディクショナリー構造へ変換。
            Dictionary <ShootingStarlightable, KyokumenWrapper> movebetuSky = Converter04.KomabetuMasus_ToMovebetuSky(
                komabetuSusumuMasus, siteiNode_yomiGenTeban.Value.ToKyokumenConst, pside_yomiGenTeban);

            // 棋譜ノード構造へ変換。
            return(Converter04.MovebetuSky_ToHubNode(movebetuSky, KifuNodeImpl.GetReverseTebanside(pside_yomiGenTeban)));
        }
Пример #5
0
        /// <summary>
        /// 利きに飛び込んでいないか(王手されていないか)、調べます。
        ///
        /// GetAvailableMove()の中では使わないでください。循環してしまいます。
        /// </summary>
        public static bool LAAA_KingSuicide(
            bool enableLog,
            SkyConst src_Sky,          //調べたい局面
            int yomuDeep,              //脳内読み手数
            int tesumi_yomiCur_forLog, //読み進めている現在の手目
            Playerside pside_genTeban, //現手番側
            GraphicalLog_File logF_kiki,
            ShootingStarlightable move_forLog
            )
        {
            bool isHonshogi = true;

            System.Diagnostics.Debug.Assert(src_Sky.Count == Masu_Honshogi.HONSHOGI_KOMAS);

            // 「相手の駒を動かしたときの利き」リスト
            // 持ち駒はどう考える?「駒を置けば、思い出王手だってある」
            List_OneAndMulti <Finger, SySet <SyElement> > sMs_effect_aiTeban = Util_LegalMove.LAAAA_GetEffect(
                enableLog,
                isHonshogi,
                src_Sky,
                pside_genTeban,
                true,// 相手盤の利きを調べます。
                logF_kiki,
                "玉自殺チェック",
                yomuDeep,
                tesumi_yomiCur_forLog,
                move_forLog);


            // 現手番側が受け手に回ったとします。現手番の、王の座標
            SyElement genTeban_kingMasu;

            if (Playerside.P2 == pside_genTeban)
            {
                // 現手番は、後手

                RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(Finger_Honshogi.GoteOh).Now);

                genTeban_kingMasu = koma.Masu;
            }
            else
            {
                // 現手番は、先手
                RO_Star_Koma koma = Util_Koma.AsKoma(src_Sky.StarlightIndexOf(Finger_Honshogi.SenteOh).Now);

                genTeban_kingMasu = koma.Masu;
            }


            // 相手の利きに、自分の王がいるかどうか確認します。
            bool mate = false;

            sMs_effect_aiTeban.Foreach_Entry((Finger koma, SySet <SyElement> kikis, ref bool toBreak) =>
            {
                foreach (Basho kiki in kikis.Elements)
                {
                    if (Util_Masu.AsMasuNumber(genTeban_kingMasu) == (int)kiki.MasuNumber)
                    {
                        mate    = true;
                        toBreak = true;
                    }
                }
            });

            return(mate);
        }
Пример #6
0
        /// <summary>
        /// 読む。
        ///
        /// 棋譜ツリーを作成します。
        /// </summary>
        /// <param name="kifu">この棋譜ツリーの現局面に、次局面をぶら下げて行きます。</param>
        /// <param name="enableLog"></param>
        /// <param name="isHonshogi"></param>
        /// <param name="logTag"></param>
        /// <returns></returns>
        public static void WAA_Yomu_Start(
            KifuTree kifu,
            bool isHonshogi,
            SsssLogGenjo log
            )
        {
            //------------------------------------------------------------
            // (>_<)次の1手の合法手の中からランダムに選ぶぜ☆!
            //------------------------------------------------------------
            //
            // バグ探し:
            //          ①次の1手の合法手のリスト作成
            //          ②ランダムに1手選ぶ
            //
            //          の2つしかやっていないんだが、合法手ではない手を返してくるんだぜ☆

#if DEBUG_STOPPABLE
            MessageBox.Show("ここでブレイク☆!", "デバッグ");
            System.Diagnostics.Debugger.Break();
            //throw new Exception("デバッグだぜ☆! エラーはキャッチできたかな~☆?(^▽^)");
#endif


            KifuNode node_yomiNext = (KifuNode)kifu.CurNode;// このノードに、ツリーをぶら下げていきます。
            int      yomuIndex     = 0;



            // TODO:ここではログを出力せずに、ツリーの先端で出力したい。
            GraphicalLog_File logF_moveKiki = new GraphicalLog_File();

            // TODO:「読む」と、ツリー構造が作成されます。
            //int[] yomuLimitter = new int[]{
            //    600, // 読みの1手目の横幅   // 王手回避漏れのために、合法手全読み(約600)は必要です。
            //    100, // 読みの2手目の横幅
            //    100, // 読みの3手目の横幅
            //    //2, // 読みの4手目の横幅
            //    //1 // 読みの5手目の横幅
            //};

            //// ↓これなら1手1秒で指せる☆
            //int[] yomuLimitter = new int[]{
            //    600, // 読みの1手目の横幅   // 王手回避漏れのために、合法手全読み(約600)は必要です。
            //    150, // 読みの2手目の横幅
            //    150, // 読みの3手目の横幅
            //    //2 // 読みの4手目の横幅
            //    //1 // 読みの5手目の横幅
            //};

            //int[] yomuLimitter = new int[]{
            //    600, // 読みの1手目の横幅   // 王手回避漏れのために、合法手全読み(約600)は必要です。
            //    600, // 読みの2手目の横幅
            //    600, // 読みの3手目の横幅
            //};

            //ok
            //int[] yomuLimitter = new int[]{
            //    0,   // 現局面は無視します。
            //    600, // 読みの1手目の横幅   // 王手回避漏れのために、合法手全読み(約600)は必要です。
            //    600, // 読みの2手目の横幅
            //};

            int[] yomuLimitter = new int[] {
                0,   // 現局面は無視します。
                600, // 読みの1手目の横幅   // 王手回避漏れのために、1手目は、合法手全読み(約600)は必要です。
                600, // 読みの2手目の横幅
                //600, // 読みの3手目の横幅
            };

#if DEBUG
            // ログの出力数を減らすために、読みを弱くします。

            //yomuLimitter = new int[]{
            //    0,  // 現局面は無視します。
            //    600, // 読みの1手目の横幅   // 王手回避漏れのために、合法手全読み(約600)は必要です。
            //    100, // 読みの2手目の横幅
            //    100 // 読みの3手目の横幅
            //};

            yomuLimitter = new int[] {
                0,   // 現局面は無視します。
                600, // 読みの1手目の横幅   // 王手回避漏れのために、1手目は、合法手全読み(約600)は必要です。
                600, // 読みの2手目の横幅
                //600 // 読みの3手目の横幅
            };

            //yomuLimitter = new int[]{
            //    600, // 読みの1手目の横幅   // 王手回避漏れのために、合法手全読み(約600)は必要です。
            //    600, // 読みの2手目の横幅
            //    600, // 読みの3手目の横幅
            //    100,
            //    100
            //};
#endif
            MoveGenArgs  yomiArgs  = new MoveGenArgsImpl(isHonshogi, yomuLimitter, logF_moveKiki);
            MoveGenGenjo yomiGenjo = new MoveGenGenjoImpl(yomiArgs, yomuIndex + 1, kifu.CurrentTesumi(), kifu.CountPside(node_yomiNext));
            MoveGenRoutine.WAAA_Yomu_Loop(node_yomiNext, yomiGenjo, log);

            if (0 < logF_moveKiki.boards.Count)//ログが残っているなら
            {
                //
                // ログの書き出し
                //
                Util_GraphicalLog.Log(
                    true,//enableLog,
                    "MoveRoutine#Yomi_NextNodes(00)新ログ",
                    "[" + Util_GraphicalLog.BoardFileLog_ToJsonStr(logF_moveKiki) + "]"
                    );

                // 書き出した分はクリアーします。
                logF_moveKiki.boards.Clear();
            }
        }